package com.iwhalecloud.bss.kite.cucc.web.service.accept.handler.module;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneMainOfferInstService;
import com.iwhalecloud.bss.kite.client.dto.inst.OfferInstDTO;
import com.iwhalecloud.bss.kite.client.vo.scene.*;
import com.iwhalecloud.bss.kite.cucc.common.constant.CuccServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.service.goods.GoodsHelper;
import com.iwhalecloud.bss.kite.cucc.service.scene.attr.CuccOperateInstAttrService;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.ztesoft.bss.common.util.ContextUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneAccessProdInstService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneFuncProdInstService;
import com.iwhalecloud.bss.kite.client.api.scene.query.IQuerySceneService;
import com.iwhalecloud.bss.kite.client.api.spec.query.IQueryOfferSpecService;
import com.iwhalecloud.bss.kite.client.dto.dirty.DirtyProdInstDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.InstAttrDTO;
import com.iwhalecloud.bss.kite.client.dto.inst.ProdInstDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.OfferDetailDTO;
import com.iwhalecloud.bss.kite.client.vo.spec.RoleButtonOfferVO;
import com.iwhalecloud.bss.kite.client.vo.spec.RoleButtonVO;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.constant.SymbolConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.attr.IUnicomRegionService;
import com.iwhalecloud.bss.kite.cucc.client.dto.attr.UnicomRegion;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccProdAttrVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.SceneNewOfferSeneVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.SceneProductModuleVO;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.service.util.LocalCacheUtils;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.dataservice.cache.AdditionalExtProdCache;
import com.iwhalecloud.bss.kite.dataservice.cache.AttrValueCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcSystemParamCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.cache.SceneMainProductCache;
import com.iwhalecloud.bss.kite.dataservice.entity.AttrValue;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.gift.KiteSceneProdRel;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.AdditionalExtProd;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferDetail;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Product;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.dto.KiteInstRelDTO;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstFunc;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.inst.graph.impl.RelEdge;
import com.iwhalecloud.bss.kite.web.context.KiteWebContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.AcceptContext;
import com.iwhalecloud.bss.kite.web.service.accept.bo.DirtyDataWrapper;
import com.iwhalecloud.bss.kite.web.service.accept.bo.SceneModule;
import com.iwhalecloud.bss.kite.web.service.accept.constant.TemplateConsts;
import com.iwhalecloud.bss.kite.web.service.accept.handler.module.AbstractModuleHandler;
import com.ztesoft.bss.base.entity.StaticAttrDO;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.base.staticdata.CoreDataProduct;
import com.ztesoft.bss.common.util.I18nUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.common.util.StringUtil;
import com.ztesoft.bss.order.base.consts.KeyValues;
import com.ztesoft.bss.order.base.unicode.UnicodeProd;
import com.ztesoft.zsmart.core.log.ZSmartLogger;

/**
 * <Description> <br>
 * 产品组件处理类 1.销售品根据产品类型分类
 *
 * @author xiao.xuzhang<br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2019年5月16日 <br>
 * @see com.iwhalecloud.bss.kite.web.service.accept.handler.module <br>
 * @since R9.0<br>
 */
public abstract class LocalAbstractProductModuleHandler extends AbstractModuleHandler {

    private static final ZSmartLogger LOGGER = ZSmartLogger.getLogger(LocalAbstractProductModuleHandler.class);

    protected static final String EXT_PRODUCT = "EXT_PRODUCT";

    @Autowired
    private IUnicomRegionService unicomRegionService;

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private IQuerySceneAccessProdInstService querySceneProdInstService;

    @Autowired
    private IQuerySceneMainOfferInstService querySceneMainOfferInstService;

    @Autowired
    private IOperateSceneInstService operateSceneInstService;

    protected List<ProductModuleVO> getViewSceneVo(String type, AcceptContext context) {
        // 批量受理当前修改销售品实例标识，存在则说明是批量受理的单个修改场景
        String curOfferInstId = context.getAcceptRequest().getCurOfferInstId();
        // 获取销售品明细规格
        Offer offer = OfferCache.get(context.getAcceptRequest().getOfferId());
        if (Objects.isNull(offer)) {
            ErrorConsts.OFFER_NOT_FOUND.throwOut();
        }

        List<ProductModuleVO> productModuleList;
        //查询这个offer下有效的接入产品
        List<ProdInstDTO> prodInstList = querySceneProdInstService
            .listEffProdInsts(context.getAcceptRequest().getSceneInstId(), context.getAcceptRequest().getCustId())
            .getResultObject();
        // 批量受理的单个修改，只处理当前修改的销售品实例
        if (KiteStringUtils.isNotEmpty(curOfferInstId)) {
            prodInstList.removeIf(prodInstDTO  -> {
                KiteOfferInst mainOfferInst = Optional.ofNullable(querySceneInstService
                    .getMainOfferInstByProdInstId(context.getAcceptRequest().getCustId(), prodInstDTO.getProdInstId()))
                    .orElse(new KiteOfferInst());
                return !KiteStringUtils.isEqual(mainOfferInst.getOfferInstId(), curOfferInstId);
            });
        }

        //FIXME 变更重提时，InitSceneOfferInstService.dealProdInstAttrsforBussChange根据service_control_scope的配置重新设置了is_edit。
        //FIXME  但不知道为啥上面取出来还是原值，目前先做个兼容重新设置一下
        prodInstList.forEach(prodInst -> {
            dealProdInstAttrsforBussChange(context.getAcceptRequest().getSceneInstId(), prodInst, context.getAcceptRequest().getCustId());
        });

        //过滤掉附加产品

        Iterator it = prodInstList.iterator();
        while (it.hasNext()) {
            ProdInstDTO prodInst = (ProdInstDTO) it.next();
            KiteOfferInst offerInst = this.querySceneMainOfferInstService.getMainOfferInstByProdInstId(context.getAcceptRequest().getCustId(), prodInst.getProdInstId());
            Product product = ProductCache.get(prodInst.getProdId());
            if ("2000".equals(product.getProdUseType()) || KiteObjectUtils.isEmpty(offerInst) || GoodsInfoTransfer
                .isAddRoleOffer(offerInst.getSpecId(), prodInst.getRoleId())) {
                it.remove();
            }
        }

        prodInstList = prodInstList.stream()
            .filter((prodInst) -> KeyConsts.PROD_FUNC_TYPE_101.equals(prodInst.getProdFuncType()))
            .collect(Collectors.toList());
        //offer是套餐或者促销
        if (StringUtils.equalsAny(offer.getOfferType(), CoreDataOffer.OFF_0005_13, CoreDataOffer.OFF_0005_11)) {
            //获取场景中有效的主套餐
            List<OfferInstDTO> mainOfferInstList = querySceneMainOfferInstService
                .getEffMainOfferInstList(context.getAcceptRequest().getSceneInstId()).getResultObject();
            //去除附加产品
            mainOfferInstList
                .removeIf(dto -> GoodsInfoTransfer.isAddRoleOffer(dto.getOfferId(), OfferCache.get(dto.getOfferId()).getCateId()));
            // 批量受理的单个修改，只处理当前修改的销售品实例
            if (KiteStringUtils.isNotEmpty(curOfferInstId)) {
                mainOfferInstList.removeIf(offerInstDTO -> !KiteStringUtils.isEqual(offerInstDTO.getOfferInstId(),
                    curOfferInstId));
            }
            List<OfferDetailDTO> offerDetails = new ArrayList<>();
            for (OfferInstDTO offerInst : mainOfferInstList) {

                offerDetails.addAll(KiteBeanUtils
                    .copyPropsForList(OfferCache.get(offerInst.getOfferId()).listAccessProdDetail(),
                        OfferDetailDTO.class));
            }
            //加载场景中所有主套餐下的产品
            productModuleList = getProdModuleVO(offerDetails, prodInstList, context);
        }
        else {
            productModuleList = getProdModule(offer, prodInstList, context);
        }
        showConfigPrintBtn(context, productModuleList, offer);
        // 处理外部参数
        dealExtParams(context, offer);
        // 此段逻辑只有互联网才执行,在基类控制
        productModuleList
            .forEach(productModuleVO -> ((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO().getProduct().add(productModuleVO));
        //((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO().setProduct(productModuleList);
        // 这里面只返回产品组件对象，角色在子组件返回
        //return ((SceneNewOfferSeneVO) context.getSceneVo()).getProduct();
        // 追加配件时，页面不展示没有实物附加商品的成员商品
        if (KiteStringUtils.isEqual("2020", context.getAcceptRequest().getServiceOfferId())) {
            productModuleList.removeIf(productModuleVO -> !GoodsHelper.containMaterialOffer(productModuleVO.getOfferId()));
        }
        return productModuleList;
    }

    private void dealProdInstAttrsforBussChange(String sceneInstId, ProdInstDTO prodInst, String custId) {
        String serviceOfferId = this.querySceneInstService.getSceneInst(sceneInstId).getServiceOfferId();
        //如果是业务变更,按service_control_scope的配置处理是否可编辑
        CuccOperateInstAttrService cuccOperateInstAttrService = SpringUtil.getBean(CuccOperateInstAttrService.class);
        ProdAttrModuleVO prodAttrModuleVO = cuccOperateInstAttrService
            .processAttrs(sceneInstId, custId, prodInst.getProdInstId(), serviceOfferId, prodInst.getProdId());
        if (KiteListUtils.isEmpty(prodAttrModuleVO.getProdAttrList())) {
            return;
        }
        Map<String, String> fieldNameAndIsEdit = prodAttrModuleVO.getProdAttrList().stream().collect(
            Collectors.toMap(ProdAttrVO::getFieldName,
                prodAttrVO -> Optional.ofNullable(prodAttrVO.getIsEdit()).orElse("T"), (v1, v2) -> v1));

        List<InstAttrDTO> prodAttrDTOs = prodInst.getInstAttrDTOS();
        List<KiteAttr> prodAttrs = querySceneInstService.listProdInstAttrs(custId, prodInst.getProdInstId());
        if (KiteListUtils.isEmpty(prodAttrDTOs) || KiteListUtils.isEmpty(prodAttrs)) {
            return;
        }

        String bizType = querySceneInstService.getExtParameterValue(sceneInstId, "bizType");
        // 订购、资源核查的追单,默认可编辑,只取配了F的属性覆盖,其他场景只有配了T的属性才可以编辑
        if (KiteStringUtils.equalsAny(serviceOfferId,LocalServiceOfferConsts.SERVICE_OFFER_FOLLOW,ServiceOfferConsts.SERVICE_OFFER_ORDER ) || KiteStringUtils.equalsAny(bizType, "1001", "1012")) {
            Iterator<String> iterator = fieldNameAndIsEdit.keySet().iterator();
            while (iterator.hasNext()) {
                String fieldName = iterator.next();
                String isEditVal = KiteMapUtils.getString(fieldNameAndIsEdit, fieldName);
                prodAttrDTOs.forEach(attrDTO -> {
                    if (KiteStringUtils.equals(attrDTO.getFieldName(), fieldName) && KiteStringUtils.isNotEmpty(isEditVal)) {
                        attrDTO.setIsEdit(isEditVal);
                    }
                });
                prodAttrs.forEach(attr -> {
                    if (KiteStringUtils.equals(attr.getFieldName(), fieldName) && KiteStringUtils.isNotEmpty(isEditVal)) {
                        attr.setIsEdit(isEditVal);
                    }
                });
            }
        } else {
            for (InstAttrDTO attrDTO : prodAttrDTOs) {
                String fieldName = attrDTO.getFieldName();
                if (KiteStringUtils.isNotEmpty(fieldNameAndIsEdit.get(fieldName))
                    && KiteStringUtils.isEqual(fieldNameAndIsEdit.get(fieldName), KeyConsts.IFTRUE_T)) {
                    attrDTO.setIsEdit(KeyConsts.IFTRUE_T);
                } else {
                    attrDTO.setIsEdit(KeyConsts.IFTRUE_F);
                }
            }
            // 修改缓存实例
            for (KiteAttr attr : prodAttrs) {
                String fieldName = attr.getFieldName();
                if (KiteStringUtils.isNotEmpty(fieldNameAndIsEdit.get(fieldName))
                    && KiteStringUtils.isEqual(fieldNameAndIsEdit.get(fieldName), KeyConsts.IFTRUE_T)) {
                    attr.setIsEdit(KeyConsts.IFTRUE_T);
                } else {
                    attr.setIsEdit(KeyConsts.IFTRUE_F);
                }
            }
        }
        operateSceneInstService.setProdInstAttrs(sceneInstId, prodInst.getProdInstId(), prodAttrs);
    }

    private void showConfigPrintBtn(AcceptContext context, List<ProductModuleVO> productModuleVOList, Offer offer) {
        String sceneInstId = context.getAcceptRequest().getSceneInstId();
        String tacheCode = this.querySceneInstService.getExtParameterValue(sceneInstId, "nodeCode");
        String taskCode = querySceneInstService.getExtParameterValue(sceneInstId, "taskCode");
        if (KiteStringUtils.isEmpty(tacheCode)) {
            tacheCode = "OrderInput";
        }
        // 有任务节点取任务节点
        String tacheCodeStr = KiteStringUtils.isEqual("OrderInput", tacheCode) ? tacheCode : taskCode;
        ((SceneNewOfferSeneVO) context.getSceneVo()).setShowConfigPrintBtn(KeyConsts.IFTRUE_F);
        ((SceneNewOfferSeneVO) context.getSceneVo()).setShowSaveDraftBtn(KeyConsts.IFTRUE_F);
        List<String> allCateId = new ArrayList<>();
        if (KiteListUtils.isNotEmpty(productModuleVOList)) {
            productModuleVOList.forEach(module -> {
                Optional.ofNullable(OfferCache.get(module.getOfferId()).getCateId()).ifPresent(allCateId::add);
            });
        }
        if (!allCateId.contains(offer.getOfferId())) {
            allCateId.add(offer.getCateId());
        }
        for (String cateId : allCateId) {
            //dcPublic配置展示配置单打印按钮的商品分类和环节编码
            List<DcPublic> dcPublics = Optional.ofNullable(DcPublicCache.get("20210306001")).orElse(Lists.newArrayList()).stream()
                .filter(dcPublic -> (KiteStringUtils.equals(dcPublic.getPkey(), cateId)
                    && KiteStringUtils.equals(dcPublic.getPcode(), tacheCodeStr))).collect(Collectors.toList());
            if (!KiteListUtils.isEmpty(dcPublics)) {
                ((SceneNewOfferSeneVO) context.getSceneVo()).setShowConfigPrintBtn(KeyConsts.IFTRUE_T);
                break;
            }
        }
        for (String cateId : allCateId.stream().distinct().collect(Collectors.toList())) {
            //dcPublic配置展示配置单打印按钮的商品分类和订购环节
            List<DcPublic> dcPublics = Optional.ofNullable(DcPublicCache.get("20210306001")).orElse(Lists.newArrayList()).stream()
                .filter(dcPublic -> (KiteStringUtils.equals(dcPublic.getPkey(), cateId)
                    && KiteStringUtils.equals(dcPublic.getPcode(), "OrderInput"))).collect(Collectors.toList());
            if (!KiteListUtils.isEmpty(dcPublics)) {
                ((SceneNewOfferSeneVO) context.getSceneVo()).setShowSaveDraftBtn(KeyConsts.IFTRUE_T);
                break;
            }
        }
    }

    /**
     * 补充前端大对象的扩展参数
     * @return
     */
    private void dealExtParams(AcceptContext context, Offer offer) {
        Map<String, Object> param = new HashMap<>();
        String serviceOfferId = context.getAcceptRequest().getServiceOfferId();
        String provinceCode = ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
        // 地图辅助查询按钮是否显示控制
        DcPublic mapAidConfig = DcPublicCache.getByPcode("2202241001", "MAP_AID_QRY_BTN", offer.getOfferId()).stream().findFirst().orElse(null);
        if (Objects.nonNull(mapAidConfig)) {
            String provConfig = mapAidConfig.getCodea();
            String businessConfig = mapAidConfig.getCodeb();
            if ((provConfig.contains(provinceCode) || KiteStringUtils.equals(provConfig, "-1"))
                && (businessConfig.contains("," + serviceOfferId + ",") || KiteStringUtils.equals(businessConfig, "-1"))) {
                param.put("showMapAidBtn", "T");
            }
        }
        // 资源预判 核查按钮是否显示控制
        DcPublic addrCheckConfig = DcPublicCache.getByPcode("2202241001", "ADDR_MAP_CHECK_BTN", offer.getOfferId()).stream().findFirst().orElse(null);
        if (Objects.nonNull(addrCheckConfig)) {
            String provConfig = addrCheckConfig.getCodea();
            String businessConfig = addrCheckConfig.getCodeb();
            if ((provConfig.contains(provinceCode) || KiteStringUtils.equals(provConfig, "-1"))
                && (businessConfig.contains("," + serviceOfferId + ",") || KiteStringUtils.equals(businessConfig, "-1"))) {
                param.put("showResCheckBtn", "T");
            }
        }
        ((SceneNewOfferSeneVO) context.getSceneVo()).setExtParams(param);
    }

    /**
     * @param offer
     * @param prodInstList
     * @param context
     * @return
     */
    private List<ProductModuleVO> getProdModule(Offer offer, List<ProdInstDTO> prodInstList, AcceptContext context) {
        List<OfferDetailDTO> offerDetails = KiteBeanUtils
            .copyPropsForList(offer.listAccessProdDetail(), OfferDetailDTO.class);

        return getProdModuleVO(offerDetails, prodInstList, context);
    }

    /**
     * 获取产品组件对象
     *
     * @param offerDetails 礼包或者套餐的产品成员明细
     * @param prodInstList 接入产品实例
     * @param context
     * @return
     */
    protected List<ProductModuleVO> getProdModuleVO(List<OfferDetailDTO> offerDetails, List<ProdInstDTO> prodInstList,
        AcceptContext context) {
        Map<String, ProductModuleVO> prodVOMap = new HashMap<>();
        List<OfferDetailDTO> tmpOfferDetails = new ArrayList<>();

        //基础销售品处理
        handleBaseOffer(context.getAcceptRequest().getOfferId(), offerDetails);
        String sceneInstId = context.getAcceptRequest().getSceneInstId();
        if(KiteStringUtils.isEmpty(sceneInstId)){
            sceneInstId = context.getSceneVo().getSceneInstId();
        }

        for (OfferDetailDTO offerDetail : offerDetails) {
            if (tmpOfferDetails.stream().anyMatch(
                tmpOfferDetail -> StringUtils.equals(tmpOfferDetail.getObjId(), offerDetail.getObjId()) && StringUtils
                    .equals(tmpOfferDetail.getRoleId(), offerDetail.getRoleId()))) {
                //过滤重复的
                continue;
            }
            tmpOfferDetails.add(offerDetail);

            Product product = ProductCache.get(offerDetail.getObjId());
            if (!Objects.equals(CoreDataProduct.PRD_0004_101, product.getProdFuncType())) {
                // 只查询接入产品
                continue;
            }

            List<ProdInstDTO> prodInsts = getProdInstList(prodInstList, offerDetail.getObjId(), offerDetail.getRoleId(),
                context.getAcceptRequest().getOfferInstId(), false);
            prodInstList.removeAll(prodInsts);

            final int maxNum = NumberUtils.toInt(offerDetail.getMaxNum(), 0);
            offerDetail.setMaxNum(String.valueOf(maxNum));

            final int minNum = prodInsts.size();

            ProductModuleVO prodVO = findProdVO(offerDetail.getOfferId(), offerDetail.getObjId(), prodVOMap, maxNum);

            for (ProdInstDTO prodInst : prodInsts) {

                // 最小值大于0，则需要默认创建成员角色
                if (Objects.nonNull(prodInst)) {
                    IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
                    String sendOfferInstId = querySceneInstService.getExtParameterValue(sceneInstId, "sendOfferInstId");
                    String receiveOfferInstId = querySceneInstService
                        .getExtParameterValue(sceneInstId, "receiveOfferInstId");
                    KiteOfferInst mainOfferInst = querySceneInstService
                        .getMainOfferInstByProdInstId(KiteWebContext.getContext().getCustId(),
                            prodInst.getProdInstId());
                    String currOfferInstId = Optional.ofNullable(mainOfferInst).map(KiteOfferInst::getOfferInstId)
                        .orElse("");
                    if (StringUtil.equals(sendOfferInstId, currOfferInstId)) {
                        offerDetail.setRoleId(LocalKeyConsts.ORIGINATOR_ROLE_ID);
                    }
                    else if (StringUtil.equals(receiveOfferInstId, currOfferInstId)) {
                        offerDetail.setRoleId(LocalKeyConsts.RECEIVER_ROLE_ID);
                    }
                    ProdRoleModuleVO prodRoleVO = genProdRoleVO(offerDetail, prodInst);
                    prodVO.getProdRole().add(prodRoleVO);
                }
            }

            if (maxNum > minNum || KiteListUtils.isEmpty(prodInsts)) {
                // 创建成员角色添加按钮
                offerDetail.setMinNum(String.valueOf(minNum));
                RoleButtonVO roleButtonVO = genRoleButtonVO(offerDetail);
                prodVO.getRoleButton().add(roleButtonVO);
            }

            if (EXT_PRODUCT.equals(offerDetail.getProdExistType())) {
                offerDetail.setMinNum("0");
                RoleButtonVO roleButtonVO = genRoleButtonVO(offerDetail);
                prodVO.getTempRoleButton().add(roleButtonVO);
            }
        }

        if (!KiteListUtils.isEmpty(prodInstList)) {
            IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
            //处理成员不在套餐里面的成员
            for (ProdInstDTO prodInst : prodInstList) {
                KiteOfferInst kiteOfferInst = querySceneInstService.getMainOfferInstByProdInstId(context.getAcceptRequest().getCustId(), prodInst.getProdInstId());
                ProductModuleVO prodVO = findProdVO(kiteOfferInst.getSpecId(), prodInst.getProdId(), prodVOMap, 1);
                ProdRoleModuleVO prodRoleVO = genProdRoleVO(null, prodInst);
                prodVO.getProdRole().add(prodRoleVO);
            }
        }

        // 产品排序
        //        return reSortFromDetailPriority(sortProdRole(transferProduct(prodVOMap)), offerDetails);
        return sortProdRole(transferProduct(prodVOMap));
    }

    /**
     * 基础销售品处理
     */
    private void handleBaseOffer(String offerId, List<OfferDetailDTO> offerDetails) {
        if (StringUtils.isBlank(offerId)) {
            return;
        }
        Offer offer = OfferCache.get(offerId);
        if (!StringUtils.equals(offer.getOfferType(), CoreDataOffer.OFF_0005_10)) {
            return;
        }
        List<OfferDetail> offerDetailList = offer.listAccessProdDetail();
        if (KiteListUtils.isEmpty(offerDetailList)) {
            return;
        }

        String baseOfferNum = DcSystemParamCache.getDcParamVal("BASE_OFFER_NUM");
        if (StringUtils.isBlank(baseOfferNum)) {
            return;
        }

        OfferDetail offerDetail = offerDetailList.get(0);
        for (OfferDetailDTO tmpOfferDetail : offerDetails) {
            if (StringUtils.equals(offerDetail.getDetailId(), tmpOfferDetail.getDetailId())) {
                int maxNum = NumberUtils.toInt(tmpOfferDetail.getMaxNum(), 0) + NumberUtils.toInt(baseOfferNum);
                tmpOfferDetail.setMaxNum(String.valueOf(maxNum));
                return;
            }
        }

    }

    //    private List<ProductModuleVO> reSortFromDetailPriority(List<ProductModuleVO> productModuleVOs, List<OfferDetailDTO> offerDetails) {
    //        List<ProductModuleVO> returnList = new ArrayList<ProductModuleVO>();
    //        offerDetails.sort((detail1, detail2) -> {
    //            String strPriority1 = detail1.getPriority();
    //            String strPriority2 = detail2.getPriority();
    //            Integer priority1 = Integer.valueOf(BigDecimal.ZERO.toString());
    //            Integer priority2 = Integer.valueOf(BigDecimal.ZERO.toString());
    //            if (!Objects.isNull(strPriority1)) {
    //                priority1 = Integer.valueOf(detail1.getPriority());
    //            }
    //            if (!Objects.isNull(strPriority2)) {
    //                priority2 = Integer.valueOf(detail2.getPriority());
    //            }
    //            return Integer.compare(priority2, priority1);
    //        });
    //
    //        for (OfferDetailDTO offerDetail : offerDetails) {
    //            for (ProductModuleVO productModuleVO : productModuleVOs) {
    //                if (KiteStringUtils.equals(productModuleVO.getProdId(), offerDetail.getObjId())) {
    //                    if (!returnList.contains(productModuleVO)) {
    //                        returnList.add(productModuleVO);
    //                    }
    //                }
    //            }
    //        }
    //
    //        return returnList;
    //    }

    /**
     * 查找prodVO
     *
     * @param prodId
     * @param prodVOMap
     * @param maxNum
     * @return
     */
    protected ProductModuleVO findProdVO(String offerId, String prodId, Map<String, ProductModuleVO> prodVOMap, int maxNum) {
        ProductModuleVO prodVO;
        if (prodVOMap.containsKey(prodId)) {
            prodVO = prodVOMap.get(prodId);
            prodVO.setProdMaxNum(String.valueOf(maxNum + Integer.parseInt(prodVO.getProdMaxNum())));
        }
        else {
            prodVO = this.genProductVO(prodId);
            prodVOMap.put(prodId, prodVO);
            prodVO.setProdMaxNum(String.valueOf(maxNum));
            prodVO.setModuleName(prodVO.getProdName());
        }
        prodVO.setOfferId(offerId);
        String offerDesc = OfferCache.get(offerId).getOfferDesc();
        prodVO.setOfferDesc(offerDesc);
        return prodVO;

    }

    /**
     * 转成ProductModuleVO
     *
     * @return
     */
    protected List<ProductModuleVO> transferProduct(Map<String, ProductModuleVO> prodVOMap) {
        List<ProductModuleVO> productModuleList = new ArrayList<>();
        // 把产品对象添加导场景实例对象
        prodVOMap.forEach((s, productModuleVO) -> {
            if (productModuleVO.getProdRole().size() == 0) {
                //区分页面是否要画大button
                productModuleVO.getRoleButton().forEach(roleButtonVO -> roleButtonVO.setButtonName(StringUtils.join(
                    roleButtonVO.getRoleName().startsWith(I18nUtil.getMessage("BSS_KITE_ACCEPT_90002")) ?
                        "" :
                        I18nUtil.getMessage("BSS_KITE_ACCEPT_90016"), roleButtonVO.getRoleName())));
            }
            productModuleVO.getTempRoleButton().forEach(roleButtonVO -> roleButtonVO.setButtonName(StringUtils.join(
                roleButtonVO.getRoleName().startsWith(I18nUtil.getMessage("BSS_KITE_ACCEPT_90002")) ?
                    "" :
                    I18nUtil.getMessage("BSS_KITE_ACCEPT_90016"), roleButtonVO.getRoleName())));
            productModuleList.add(productModuleVO);
        });

        //把同角色不同产品的过滤掉
        productModuleList.forEach(productModuleVO -> productModuleVO.getRoleButton().removeIf(roleButtonVO -> {
            for (ProductModuleVO productModuleTemp : productModuleList) {
                for (ProdRoleModuleVO prodRoleModuleVO : productModuleTemp.getProdRole()) {
                    if (roleButtonVO.getProdRoleId().equals(prodRoleModuleVO.getProdRoleId()) && !roleButtonVO
                        .getProdId().equals(prodRoleModuleVO.getProdId())) {
                        return true;
                    }
                }
            }
            return false;
        }));
        productModuleList.removeIf(productModuleVO -> productModuleVO.getRoleButton().size() == 0
            && productModuleVO.getProdRole().size() == 0);

        return productModuleList;
    }

    /**
     * 根据产品标识和角色标识找到对应的角色
     *
     * @param prodInstList
     * @param prodId
     * @param roleId
     * @return
     */
    protected List<ProdInstDTO> getProdInstList(List<ProdInstDTO> prodInstList, String prodId, String roleId,
        String offerInstId, boolean isParent) {
        List<ProdInstDTO> filterProdInstList = new ArrayList<>();
        for (ProdInstDTO prodInst : prodInstList) {
            if (prodId.equals(prodInst.getProdId()) && roleId.equals(prodInst.getRoleId())) {
                filterProdInstList.add(prodInst);
                continue;
            }
            //当产品的角色和产品ID，都没有匹配上时，在查询当前产品实例的边，根据边上的明细进行比较
            IQuerySceneAccessProdInstService querySceneAccessProdInstService = SpringUtil
                .getBean(IQuerySceneAccessProdInstService.class);
            List<RelEdge> parentInstRels = querySceneAccessProdInstService
                .listParentInstRels(prodInst.getOwnerCustId(), prodInst.getProdInstId(), InstType.PROD_INST)
                .getResultObject();

            for (RelEdge instRel : parentInstRels) {
                if (KeyConsts.ACTION_TYPE_D.equals(instRel.getActionType().name())) {
                    continue;
                }
                if (isParent) {
                    // 根据父类的实例ID，查询所有的子关系
                    List<RelEdge> subOfferInstRels = querySceneAccessProdInstService
                        .listSubInstRels(prodInst.getOwnerCustId(), offerInstId, InstType.GIFT_OFFER_INST)
                        .getResultObject();
                    // 从子关系中获取当前instRel中的目标实例ID的关系边；
                    List<RelEdge> offerInstRels = subOfferInstRels.stream().filter(
                        subOfferInstRel -> !KeyConsts.ACTION_TYPE_D.equals(subOfferInstRel.getActionType().name())
                            && StringUtils.equals(instRel.getTargetInstId(), subOfferInstRel.getTargetInstId()))
                        .collect(Collectors.toList());
                    // 当前instRel中的目标实例ID在子关系中不存在，则进行下一次循环；
                    if (KiteListUtils.isEmpty(offerInstRels)) {
                        continue;
                    }
                    if (StringUtils.equals(prodId, prodInst.getProdId()) && StringUtils
                        .equals(roleId, instRel.getRoleId())) {
                        filterProdInstList.add(prodInst);
                        break;
                    }
                }
                else {
                    if (StringUtils.equals(offerInstId, instRel.getTargetInstId()) && StringUtils
                        .equals(prodId, prodInst.getProdId()) && StringUtils.equals(roleId, instRel.getRoleId())) {
                        filterProdInstList.add(prodInst);
                        break;
                    }
                }
            }
        }
        return filterProdInstList;
    }

    /**
     * Description: <br>
     * 生成产品对象
     *
     * @param prodId
     * @return <br>
     * @author xiao.xuzhang<br>
     * @taskId <br>
     */
    protected ProductModuleVO genProductVO(String prodId) {
        ProductModuleVO vo = new ProductModuleVO();
        Product product = ProductCache.get(prodId);
        vo.setProdId(product.getProdId());
        vo.setProdName(product.getProdName());
        vo.setProdFuncType(product.getProdFuncType());
        return vo;
    }

    /**
     * Description: <br>
     * 创建产品角色添加按钮对象
     *
     * @param offerDetail
     * @return <br>
     * @author xiao.xuzhang<br>
     * @taskId <br>
     */
    protected RoleButtonVO genRoleButtonVO(OfferDetailDTO offerDetail) {
        RoleButtonVO vo = new RoleButtonVO();
        if (EXT_PRODUCT.equals(offerDetail.getProdExistType())) {
            //可选包加装
            List<AdditionalExtProd> additionalExtProds = AdditionalExtProdCache.getInst()
                .getAdditionalOffer(offerDetail.getGroupOptDays(), offerDetail.getObjId(), offerDetail.getRoleId());
            additionalExtProds.forEach(additionalExtProd -> {
                vo.getOfferList().add(KiteBeanUtils.transform(additionalExtProd, RoleButtonOfferVO.class));
            });
        }
        vo.setOfferDetailId(offerDetail.getDetailId());
        vo.setProdId(offerDetail.getObjId());
        vo.setProdRoleId(offerDetail.getRoleId());
        vo.setCurrentNum(offerDetail.getMinNum());
        vo.setMaxNum(offerDetail.getMaxNum());
        vo.setRoleName(offerDetail.getRoleName());
        final String addButtonString = I18nUtil.getMessage("BSS_KITE_ACCEPT_90002");
        vo.setButtonName(
            (offerDetail.getRoleName().startsWith(addButtonString) ? "" : addButtonString) + offerDetail.getRoleName());

        return vo;
    }

    /**
     * Description: <br>
     * 创建销售品成员角色
     *
     * @param offerDetail
     * @param prodInst
     * @return <br>
     * @author xiao.xuzhang<br>
     * @taskId <br>
     */
    protected ProdRoleModuleVO genProdRoleVO(OfferDetailDTO offerDetail, ProdInstDTO prodInst) {
        ProdRoleModuleVO vo = new ProdRoleModuleVO();
        if (offerDetail != null) {
            vo.setModuleName(offerDetail.getRoleName());
            vo.setProdId(offerDetail.getObjId());
            vo.setProdRoleName(offerDetail.getRoleName());
            vo.setProdRoleId(offerDetail.getRoleId());
            vo.setMinNum(offerDetail.getMinNum());
            vo.setMaxNum(offerDetail.getMaxNum());
            vo.setOfferDetailId(offerDetail.getDetailId());
            if (EXT_PRODUCT.equals(offerDetail.getProdExistType())) {
                vo.setAdditionalOfferAdd(true);
            }
        }
        else {
            vo.setModuleName(prodInst.getProdName());
            vo.setProdId(prodInst.getProdId());
            vo.setProdRoleName(prodInst.getProdName());
            vo.setProdRoleId(prodInst.getRoleId());
            vo.setMinNum("0");
            vo.setMaxNum("1");
            vo.setOfferDetailId("-1");
        }

        if ((vo.getMinNum().equals(vo.getMaxNum()))) {
            // 相等的时候不给它删除
            vo.setDeleteFlag(TemplateConsts.FALSE_F);
            vo.setFreeFlag(TemplateConsts.FALSE_F);
        }
        else {
            vo.setDeleteFlag(TemplateConsts.TRUE_T);
            if (!ActionType.A.name().equals(prodInst.getActionType())) {
                // 不是当前场景新增的实例才允许操作 游离
                vo.setFreeFlag(TemplateConsts.TRUE_T);
            }
        }

        vo.setProdInstId(prodInst.getProdInstId());
        vo.setActionType(prodInst.getActionType());

        //属性
        List<CuccProdAttrVO> cuccProdAttrList = new ArrayList<>();
        Optional.ofNullable(prodInst.getInstAttrDTOS()).ifPresent(instAttrs -> {
            instAttrs
                .forEach(kiteAttr -> cuccProdAttrList.add(KiteBeanUtils.transform(kiteAttr, CuccProdAttrVO.class)));
        });
        cuccProdAttrList.removeIf(attr -> KeyConsts.PROD_ATTR_SHOW_TYPE_H.equals(attr.getShowType()) || KeyConsts.PROD_ATTR_SHOW_TYPE_E.equals(attr.getShowType()));
        ProdAttrModuleVO prodAttrModule = new ProdAttrModuleVO();
        List<ProdAttrVO> prodAttrList = new ArrayList<>(cuccProdAttrList);
        prodAttrList.sort(Comparator.comparing(prodAttrVO -> NumberUtils.toInt(prodAttrVO.getOrderId(), 0)));
        prodAttrModule.setProdAttrList(prodAttrList);
        vo.setProdAttr(prodAttrModule);

        return vo;
    }

    /**
     * 产品排序顺序
     *
     * @return
     */
    protected Map<String, Integer> getSortMap() {
        // 顺序如下单商品》发端》收端
        Map<String, Integer> sortMap = new HashMap<>();
        sortMap.put(LocalKeyConsts.ORIGINATOR_ROLE_ID, 100);
        sortMap.put(LocalKeyConsts.RECEIVER_ROLE_ID, 200);
        return sortMap;
    }

    /**
     * 根据产品排序
     */
    protected List<ProductModuleVO> sortProdRole(List<ProductModuleVO> productModuleList) {
        // 剔除ProdRole为空的产品,兼容融合商品，配了资费产品和主套餐关系后,这里把资费产品加进来会报错。
        if (KiteListUtils.isNotEmpty(productModuleList)) {
            productModuleList = productModuleList.stream()
                .filter(productModule -> KiteListUtils.isNotEmpty(productModule.getProdRole()))
                .collect(Collectors.toList());
        }

        productModuleList.sort((o1, o2) -> {
            int prodSortNum1 = 99;
            if (getSortMap().containsKey(o1.getProdRole().get(0).getProdRoleId())) {
                prodSortNum1 = getSortMap().get(o1.getProdRole().get(0).getProdRoleId());
            }

            if (o1.getProdRole().size() == 0) {
                prodSortNum1 = 99 + prodSortNum1;
            }

            int prodSortNum2 = 99;
            if (getSortMap().containsKey(o2.getProdRole().get(0).getProdRoleId())) {
                prodSortNum2 = getSortMap().get(o2.getProdRole().get(0).getProdRoleId());
            }

            if (o2.getProdRole().size() == 0) {
                prodSortNum2 = 99 + prodSortNum2;
            }

            return Integer.compare(prodSortNum1, prodSortNum2);
        });

        return productModuleList;
    }

    /**
     * 获取礼包产品组件对象
     *
     * @param prodInstList 接入产品实例
     * @param context
     * @return
     */
    protected List<ProductModuleVO> getGiftProdModuleVO(List<ProdInstDTO> prodInstList, AcceptContext context) {
        final String offerId = context.getAcceptRequest().getOfferId();
        //主产品和加装产品
        List<KiteSceneProdRel> kiteSceneProdRelList = SceneMainProductCache.get(offerId);
        if (KiteListUtils.isEmpty(kiteSceneProdRelList)) {
            ErrorConsts.OFFER_WEB_SCENE_NOT_FOUND.throwOut(offerId);
        }

        List<OfferDetailDTO> offerDetails = SpringUtil.getBean(IQueryOfferSpecService.class)
            .listGiftOfferProdDetails(context.getAcceptRequest().getOfferId()).getResultObject();
        getExtProductDetail(offerId, offerDetails);

        Map<String, ProductModuleVO> productModuleMap = new HashMap<>();

        //取礼包和套餐的最小限制，来设置成员的可删除
        genProductModule(null, kiteSceneProdRelList, offerDetails, productModuleMap, prodInstList, context, true);
        dealGiftOfferMinProdDel(context, offerId, offerDetails, productModuleMap);
        // 产品排序
        return sortProdRole(transferProduct(productModuleMap));
    }

    /**
     * 礼包产品对象构造
     *
     * @param productModuleVO      加装的有值 主产品为null
     * @param kiteSceneProdRelList
     * @param offerDetails         礼包明细
     * @param productModuleMap
     * @param prodInstList         产品实例
     * @param isParent             true：主产品
     */
    private void genProductModule(ProductModuleVO productModuleVO, List<KiteSceneProdRel> kiteSceneProdRelList,
        List<OfferDetailDTO> offerDetails, Map<String, ProductModuleVO> productModuleMap,
        List<ProdInstDTO> prodInstList, AcceptContext context, boolean isParent) {
        //构造页面对象
        for (KiteSceneProdRel kiteSceneProdRel : kiteSceneProdRelList) {
            //查找明细
            OfferDetailDTO offerDetail = findOfferDetail(offerDetails, kiteSceneProdRel.getProdId(),
                kiteSceneProdRel.getRoleId());
            if (Objects.isNull(offerDetail)) {
                ErrorConsts.OFFER_DETAIL_NOT_FOUND.throwOut(kiteSceneProdRel.getProdId(), kiteSceneProdRel.getRoleId());
            }

            //如果是主产品的话 构造产品组件对象
            if (isParent) {
                if (productModuleMap.containsKey(kiteSceneProdRel.getProdId())) {
                    productModuleVO = productModuleMap.get(kiteSceneProdRel.getProdId());
                }
                else {
                    productModuleVO = genProductVO(kiteSceneProdRel.getProdId());
                    productModuleMap.put(kiteSceneProdRel.getProdId(), productModuleVO);
                }
            }
            //查询产品实例
            IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
            List<ProdInstDTO> currProdInstList = getProdInstList(prodInstList, kiteSceneProdRel.getProdId(),
                kiteSceneProdRel.getRoleId(), context.getAcceptRequest().getOfferInstId(), isParent);
            if (!KiteListUtils.isEmpty(currProdInstList)) {
                for (ProdInstDTO instDTO : currProdInstList) {
                    //构造角色对象
                    ProdRoleModuleVO prodRoleVO = genProdRoleVO(offerDetail, instDTO);
                    //配置了多个全屋wifi套餐的礼包，展示全屋wifi所属的套餐名称
                    if (StringUtils.equals(offerDetail.getObjId(), UnicodeProd.PROD_100110)) {
                        List<KiteInstRelDTO> mainOfferObjInstRels = querySceneInstService
                            .listInstRelsByZInst(context.getAcceptRequest().getCustId(), InstType.PROD_INST,
                                instDTO.getProdInstId(), InstType.MAIN_OFFER_INST);
                        if (Objects.nonNull(mainOfferObjInstRels) && mainOfferObjInstRels.size() > 0) {
                            KiteInstRelDTO mainOfferObjInstRel = mainOfferObjInstRels.get(0);
                            Offer offer = OfferCache.get(mainOfferObjInstRel.getaSpecId());
                            StringBuilder roleName = new StringBuilder(prodRoleVO.getProdRoleName()).append(" ")
                                .append(offer.getOfferName());
                            prodRoleVO.setProdRoleName(roleName.toString());
                        }
                        else {
                            List<KiteInstRelDTO> promotionOfferRels = querySceneInstService
                                .listInstRelsByZInst(context.getAcceptRequest().getCustId(), InstType.PROD_INST,
                                    instDTO.getProdInstId(), InstType.PROMOTION_OFFER_INST);
                            if (Objects.nonNull(promotionOfferRels) && promotionOfferRels.size() > 0) {
                                KiteInstRelDTO promotionOfferRel = promotionOfferRels.get(0);
                                Offer offer = OfferCache.get(promotionOfferRel.getaSpecId());
                                StringBuilder roleName = new StringBuilder(prodRoleVO.getProdRoleName()).append(" ")
                                    .append(offer.getOfferName());
                                prodRoleVO.setProdRoleName(roleName.toString());
                            }
                        }
                    }
                    productModuleVO.getProdRole().add(prodRoleVO);
                }

                if (isParent) {
                    //处理加装产品
                    genProductModule(productModuleVO, kiteSceneProdRel.getExtraProduct(), offerDetails,
                        productModuleMap, prodInstList, context, false);
                }
            }

            //构造加装按钮对象
            if (currProdInstList.size() < NumberUtils.toInt(kiteSceneProdRel.getMaxNum())) {
                // 如果礼包中不存在明细对应的主套餐，则不显示此明细的添加按钮
                if (!isDetailOfNonExistMainOffer(offerDetail, context)) {
                    offerDetail.setMinNum(String.valueOf(currProdInstList.size()));
                    offerDetail.setMaxNum(kiteSceneProdRel.getMaxNum());
                    RoleButtonVO roleButtonVO = genRoleButtonVO(offerDetail);
                    productModuleVO.getRoleButton().add(roleButtonVO);
                }
            }

            //礼包中第二条宽带特殊处理，只保留第二条条宽带的角色对象；
            ProductModuleVO clone = KiteObjectUtils.clone(productModuleVO);
            Iterator<ProdRoleModuleVO> voItems = productModuleVO.getProdRole().iterator();
            while (voItems.hasNext()) {
                ProdRoleModuleVO vo = voItems.next();
                for (ProdRoleModuleVO cloneVO : clone.getProdRole()) {
                    if (KiteStringUtils.equals(cloneVO.getProdRoleId(), KeyConsts.SECOND_BROADBAND_ROLE_ID)
                        && KiteStringUtils.equals(cloneVO.getProdInstId(), vo.getProdInstId()) && !(KiteStringUtils
                        .equals(cloneVO.getProdRoleId(), vo.getProdRoleId()))) {
                        voItems.remove();
                    }
                }
            }

        }
    }

    /**
     * 礼包中是否不存在明细对应的主套餐
     *
     * @param offerDetail
     * @param context
     * @return
     */
    private boolean isDetailOfNonExistMainOffer(OfferDetailDTO offerDetail, AcceptContext context) {
        String offerId = offerDetail.getOfferId();
        if (!KeyConsts.OFFER_TYPE_11.equals(OfferCache.get(offerId).getOfferType())) {
            return false;
        }
        String sceneInstId = context.getAcceptRequest().getSceneInstId();
        String giftOfferId = context.getAcceptRequest().getOfferId();
        String custId = context.getAcceptRequest().getCustId();
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        KiteOfferInst giftOfferInst = querySceneInstService.getGiftOfferInst(sceneInstId, giftOfferId);
        if (giftOfferInst == null) {
            return false;
        }
        return querySceneInstService.listMainOfferInstsFromGiftOfferInst(custId, giftOfferInst.getOfferInstId())
            .stream().noneMatch(t -> offerId.equals(t.getOfferId()));
    }

    /**
     * 查询明细
     *
     * @param OfferDetailList
     * @param prodId
     * @param roleId
     * @return
     */
    private OfferDetailDTO findOfferDetail(List<OfferDetailDTO> OfferDetailList, String prodId, String roleId) {
        for (OfferDetailDTO offerDetail : OfferDetailList) {
            if (KiteStringUtils.equals(offerDetail.getObjId(), prodId) && KiteStringUtils
                .equals(offerDetail.getRoleId(), roleId)) {
                return offerDetail;
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected List<? extends ModuleVO> refresh(AcceptContext context, SceneModule sceneModule,
        DirtyDataWrapper dirtyDataWrapper) {
        List<DirtyProdInstDTO> dirtyProdInsts = dirtyDataWrapper.listDirtyProdInsts(ActionType.D);
        if (dirtyProdInsts.size() > 0) {
            //处理roleButton
            List<ProductModuleVO> productModuleList = ((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO().getProduct();
            AcceptContext cloneContext = KiteObjectUtils.clone(context);
            ((SceneNewOfferSeneVO) cloneContext.getSceneVo()).getSceneProductModuleVO().getProduct().clear();
            List<ProductModuleVO> productList = (List<ProductModuleVO>) execute(cloneContext, sceneModule);
            productModuleList.forEach(productModuleVO -> {
                productModuleVO.setRoleButton(productList.stream()
                    .filter(product -> StringUtils.equals(product.getProdId(), productModuleVO.getProdId()))
                    .filter(product -> CollectionUtils.isNotEmpty(product.getRoleButton())).findFirst()
                    .orElse(productModuleVO).getRoleButton());
            });

            productList.removeIf(product -> productModuleList.stream()
                .anyMatch(productModule -> StringUtils.equals(product.getProdId(), productModule.getProdId())));
            productModuleList.addAll(productList);

        }
        SceneVO sceneVO = context.getSceneVo();
        if(KiteObjectUtils.isEmpty(sceneVO)){
            SceneProductModuleVO sceneProductModuleVO = new SceneProductModuleVO();
            return sceneProductModuleVO.getProduct();
        }
        SceneProductModuleVO sceneProductModuleVO = ((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO();
        if(KiteObjectUtils.isEmpty(sceneProductModuleVO)){
            sceneProductModuleVO = new SceneProductModuleVO();
            return sceneProductModuleVO.getProduct();
        }
        return ((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO().getProduct();
    }

    /**
     * 产品组件刷新后，重新计算RoleButtonVO
     *
     * @param context
     * @param sceneModule
     */
    @Override
    protected void afterRefresh(AcceptContext context, SceneModule sceneModule) {
        List<ProductModuleVO> productModuleVOs = Lists.newArrayList();
        if (!KiteObjectUtils.isEmpty(context) && !KiteObjectUtils.isEmpty(context.getSceneVo())) {
            SceneNewOfferSeneVO sceneNewOfferSeneVO = (SceneNewOfferSeneVO) context.getSceneVo();
            if (!KiteObjectUtils.isEmpty(sceneNewOfferSeneVO) && !KiteObjectUtils
                .isEmpty(sceneNewOfferSeneVO.getSceneProductModuleVO())) {
                productModuleVOs = sceneNewOfferSeneVO.getSceneProductModuleVO().getProduct();
            }
        }
        if (KiteListUtils.isNotEmpty(productModuleVOs)) {
            handleExtOffer(productModuleVOs);
            computeRoleButton(productModuleVOs);
        }
    }

    @Override
    public void afterExecute(AcceptContext context, SceneModule sceneModule) {
        List<ProductModuleVO> productModuleVOs = null;
        if (context.getSceneVo() instanceof SceneContractVO) {
            return;
        }
        else {
            productModuleVOs = ((SceneNewOfferSeneVO) context.getSceneVo()).getSceneProductModuleVO().getProduct();
        }

        handleExtOffer(productModuleVOs);

        computeRoleButton(productModuleVOs);
    }

    /**
     * 重新计算rolebutton数量
     *
     * @param productModuleVOs
     */
    private void computeRoleButton(List<ProductModuleVO> productModuleVOs) {
        for (ProductModuleVO productModuleVO : productModuleVOs) {
            List<RoleButtonVO> roleButtonVOs = productModuleVO.getRoleButton();
            if (CollectionUtils.isNotEmpty(roleButtonVOs)) {
                for (RoleButtonVO roleButtonVO : roleButtonVOs) {
                    String roleId = roleButtonVO.getProdRoleId();
                    long amount = productModuleVO.getProdRole().stream().filter(t -> roleId.equals(t.getProdRoleId()))
                        .count();
                    roleButtonVO.setCurrentNum(String.valueOf(amount));
                }
            }
        }
    }

    /**
     * 加装可选包产品实例处理
     * 将加装产品实例按加装可选包分类，并且始终展示加装可选包按钮，直到所有加装可选包都购买了
     *
     * @param productModuleVOs
     */
    private void handleExtOffer(List<ProductModuleVO> productModuleVOs) {
        //多个加装可选包的情况处理
        Map<String, Map<String, List<ProdRoleModuleVO>>> prodExtOfferProdRoleModuleMap = new HashMap<>(); //存放 产品-加装可选包-产品实例 key是产品标识
        Map<String, ProductModuleVO> productModuleMap = new HashMap<>(); //存放产品-产品对象 key是产品标识

        computeExtOffer(prodExtOfferProdRoleModuleMap, productModuleMap, productModuleVOs);

        dealExtOffer(productModuleMap, prodExtOfferProdRoleModuleMap, productModuleVOs);

    }

    /**
     * 处理加装可选包
     *
     * @param productModuleMap
     * @param prodExtOfferProdRoleModuleMap
     * @param productModuleVOs
     */
    private void dealExtOffer(Map<String, ProductModuleVO> productModuleMap,
        Map<String, Map<String, List<ProdRoleModuleVO>>> prodExtOfferProdRoleModuleMap,
        List<ProductModuleVO> productModuleVOs) {
        if (!productModuleMap.isEmpty()) {
            prodExtOfferProdRoleModuleMap.forEach((prodId, extOfferProdRoleModuleMap) -> {
                productModuleVOs.removeIf(productModuleVO -> productModuleVO.getProdId().equals(prodId));
                ProductModuleVO productModuleVO = productModuleMap.get(prodId);
                productModuleVO.setExtOfferId("");
                productModuleVO.getProdRole().clear();

                // 构造prodrole对象
                List<ProductModuleVO> tempProductModules = new ArrayList<>();
                List<String> offerIds = new ArrayList<>();
                extOfferProdRoleModuleMap.forEach((offerId, prodRoleModuleVOS) -> {
                    offerIds.add(offerId);
                    if ("-1".equals(offerId)) {
                        offerId = "";
                    }
                    ProductModuleVO tempProductModule = KiteObjectUtils.clone(productModuleVO);
                    tempProductModule.setExtOfferId(offerId);
                    tempProductModule.setProdRole(prodRoleModuleVOS);
                    if (tempProductModule.getRoleButton().size() == 0) {
                        List<RoleButtonVO> roleButtonVOList = KiteObjectUtils
                            .clone(productModuleVO.getTempRoleButton());
                        tempProductModule.setRoleButton(roleButtonVOList);
                    }

                    tempProductModules.add(tempProductModule);
                });

                //                tempProductModules.sort((o1, o2) -> {
                //                    long prodSortNum1 = Long.valueOf(o1.getProdRole().get(0).getProdInstId());
                //
                //                    long prodSortNum2 = Long.valueOf(o2.getProdRole().get(0).getProdInstId());
                //
                //                    return Long.compare(prodSortNum1, prodSortNum2);
                //                });

                productModuleVOs.addAll(tempProductModules);
                //加装按钮下拉框去除已经购买的加装可选包，如果加装可选包都买了，那么整个按钮都去掉
                List<RoleButtonVO> roleButtonVOList = KiteObjectUtils.clone(productModuleVO.getTempRoleButton());
                productModuleVO.setRoleButton(roleButtonVOList);
                productModuleVO.getRoleButton().get(0).getOfferList()
                    .removeIf(roleButtonOfferVO -> offerIds.contains(roleButtonOfferVO.getOfferId()));
                if (productModuleVO.getRoleButton().get(0).getOfferList().size() > 0) {
                    productModuleVOs.add(productModuleVO);
                }

            });

            sortProdRole(productModuleVOs);
        }
    }

    /**
     * 加装可选包和实例计算分类
     *
     * @param prodExtOfferProdRoleModuleMap
     * @param productModuleMap
     * @param productModuleVOs
     */
    private void computeExtOffer(Map<String, Map<String, List<ProdRoleModuleVO>>> prodExtOfferProdRoleModuleMap,
        Map<String, ProductModuleVO> productModuleMap, List<ProductModuleVO> productModuleVOs) {
        for (ProductModuleVO productModuleVO : productModuleVOs) {
            Map<String, List<ProdRoleModuleVO>> extOfferProdRoleModuleMap = new HashMap<>(); //存放加装可选包-产品实例 key是加装可选包id
            List<ProdRoleModuleVO> prodRoleModuleVOList = productModuleVO.getProdRole();
            if (KiteListUtils.isNotEmpty(prodRoleModuleVOList) && productModuleVO.getTempRoleButton().size() > 0
                && productModuleVO.getTempRoleButton().get(0).getOfferList().size() > 0 && productModuleVO.getProdId()
                .equals(UnicodeProd.PROD_100003)) {
                // 暂时只处理固话
                List<String> offerIds = productModuleVO.getTempRoleButton().get(0).getOfferList().stream()
                    .map(RoleButtonOfferVO::getOfferId).collect(Collectors.toList());
                prodRoleModuleVOList.forEach(prodRoleModuleVO -> {
                    List<ProdSubOfferTypeVO> prodSubOfferTypeVOList = prodRoleModuleVO.getProdSubOffer()
                        .getProdSubOfferTypeList();
                    boolean isDeal = Optional.ofNullable(prodSubOfferTypeVOList).map(tempProdSubOfferTypeVOList -> {
                        //所有可选包列表
                        List<ProdSubOfferVO> offerLists = new ArrayList<>();
                        tempProdSubOfferTypeVOList.forEach(
                            tempProdSubOfferTypeVO -> Optional.ofNullable(tempProdSubOfferTypeVO.getProdSubOfferList())
                                .map(offerLists::addAll));
                        String offerId = "-1";
                        //计算加装可选包
                        for (String tmpOfferId : offerIds) {
                            String buyOfferId = offerLists.stream().filter(
                                prodSubOfferVO -> prodSubOfferVO.getOfferId().equals(tmpOfferId) && !prodSubOfferVO
                                    .isNotCheck()).findFirst().map(ProdSubOfferVO::getOfferId).orElse(null);
                            if (buyOfferId != null) {
                                offerId = buyOfferId;
                                break;
                            }
                        }
                        //按加装可选包进行分类
                        putProdRole(extOfferProdRoleModuleMap, offerId, prodRoleModuleVO);
                        return true;
                    }).orElse(false);
                    if (!isDeal) {
                        putProdRole(extOfferProdRoleModuleMap, "-1", prodRoleModuleVO);
                    }

                });

                productModuleMap.put(productModuleVO.getProdId(), productModuleVO);
                putProd(prodExtOfferProdRoleModuleMap, productModuleVO.getProdId(), extOfferProdRoleModuleMap);
            }
        }
    }

    /**
     * 存产品下的ProdRoleModuleVO
     *
     * @param prodExtOfferProdRoleModuleMap
     * @param key                           产品标识
     * @param extOfferProdRoleModuleMap
     */
    private void putProd(Map<String, Map<String, List<ProdRoleModuleVO>>> prodExtOfferProdRoleModuleMap, String key,
        Map<String, List<ProdRoleModuleVO>> extOfferProdRoleModuleMap) {
        if (prodExtOfferProdRoleModuleMap.containsKey(key)) {
            Map<String, List<ProdRoleModuleVO>> prodRoleModule = prodExtOfferProdRoleModuleMap.get(key);
            extOfferProdRoleModuleMap.forEach((offerId, prodRoleModuleVOS) -> {
                if (prodRoleModule.containsKey(offerId)) {
                    prodRoleModule.get(offerId).addAll(prodRoleModuleVOS);
                }
                else {
                    prodRoleModule.put(offerId, prodRoleModuleVOS);
                }
            });
        }
        else {
            prodExtOfferProdRoleModuleMap.put(key, extOfferProdRoleModuleMap);
        }

    }

    /**
     * 存ProdRoleModuleVO
     *
     * @param extOfferProdRoleModuleMap
     * @param key                       加装可选包标识
     * @param prodRoleModuleVO
     */
    private void putProdRole(Map<String, List<ProdRoleModuleVO>> extOfferProdRoleModuleMap, String key,
        ProdRoleModuleVO prodRoleModuleVO) {
        if (extOfferProdRoleModuleMap.containsKey(key)) {
            extOfferProdRoleModuleMap.get(key).add(prodRoleModuleVO);
        }
        else {
            extOfferProdRoleModuleMap.put(key, Lists.newArrayList(prodRoleModuleVO));
        }

    }

    /**
     * 处理可选包加装的明细
     *
     * @param offerId 主套餐标识
     * @return
     */
    protected void getExtProductDetail(String offerId, List<OfferDetailDTO> offerDetails) {
        //处理主套餐可选包加装的
        List<OfferDetailDTO> offerDetailList = KiteBeanUtils
            .copyPropsForList(AdditionalExtProdCache.getInst().getDetail(offerId), OfferDetailDTO.class);
        //加装的都设置为0
        offerDetailList.forEach(offerDetailDTO -> {
            if (offerDetails.stream().noneMatch(
                additionalExtProd -> StringUtils.equals(offerDetailDTO.getObjId(), additionalExtProd.getObjId())
                    && StringUtils.equals(offerDetailDTO.getRoleId(), additionalExtProd.getRoleId()))) {
                offerDetailDTO.setMinNum("0");
                offerDetailDTO.setProdExistType(EXT_PRODUCT);
                offerDetailDTO.setGroupOptDays(offerId);
                offerDetails.add(offerDetailDTO);
            }
        });
    }

    private void dealGiftOfferMinProdDel(AcceptContext context, String offerId, List<OfferDetailDTO> offerDetails,
        Map<String, ProductModuleVO> productModuleMap) {
        if (KiteMapUtils.isEmpty(productModuleMap)) {
            return;
        }
        List<OfferDetailDTO> offerDetailDTOList = SpringUtil.getBean(IQueryOfferSpecService.class)
            .listOfferDetails(offerId).getResultObject();
        if (KiteListUtils.isNotEmpty(offerDetailDTOList)) {
            //            Map<String, List<OfferDetailDTO>> detailsMap = dealSortDetails(offerDetailDTOList);
            //            CoreDataOffer.OFF_0005_11
            //            List<OfferDetailDTO> offerDetailDto = detailsMap.get(CoreDataOffer.OFF_0005_11);
            for (OfferDetailDTO dto : offerDetailDTOList) {
                if (null != dto) {
                    String mOfferId = dto.getObjId();
                    String minNum = dto.getMinNum();
                    if (KeyConsts.ZERO.equals(minNum)) {
                        for (OfferDetailDTO detailDTO : offerDetails) {
                            if (null != detailDTO) {
                                String detailOfferId = detailDTO.getOfferId();
                                if (mOfferId.equals(detailOfferId)) {
                                    String objId = detailDTO.getObjId();
                                    //检查主产品下副产品成员符合要求也是允许删除的
                                    productModuleMap = checkProductModuleMap(context, productModuleMap, objId,
                                        TemplateConsts.TRUE_T);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    public Map<String, ProductModuleVO> checkProductModuleMap(AcceptContext context,
        Map<String, ProductModuleVO> productModuleMap, String objId, String falg) {
        for (Map.Entry<String, ProductModuleVO> entry : productModuleMap.entrySet()) {
            ProductModuleVO productModuleVO = entry.getValue();
            if (null != productModuleVO) {
                List<ProdRoleModuleVO> prodRoleList = productModuleVO.getProdRole();
                IQuerySceneService querySceneService = SpringUtil.getBean(IQuerySceneService.class);
                KiteSceneInst sceneInst = querySceneService.getSceneInst(context.getAcceptRequest().getSceneInstId());
                if (KiteListUtils.isNotEmpty(prodRoleList)) {
                    IQuerySceneAccessProdInstService querySceneAccessProdInstService = SpringUtil
                        .getBean(IQuerySceneAccessProdInstService.class);
                    for (ProdRoleModuleVO prodVo : prodRoleList) {
                        String prodId = prodVo.getProdId();
                        if (objId.equals(prodId)) {
                            prodVo.setDeleteFlag(falg);
                            KiteProdInst prodInst = querySceneAccessProdInstService
                                .getProdInst(sceneInst.getCustId(), prodVo.getProdInstId());
                            if (Objects.isNull(prodInst) || ActionType.A.equals(prodInst.getActionType())) {
                                // 如果这个实例是当前场景新增的，就不允许它有游离的按钮了
                                continue;
                            }
                            prodVo.setFreeFlag(TemplateConsts.TRUE_T);
                        }
                    }
                    productModuleVO.setProdRole(prodRoleList);
                }
            }
        }
        return productModuleMap;
    }

    //处理预览页面展示新旧值
    protected void dealPreviewOldAndNewValues(List<ProductModuleVO> productList, String sceneInstId) {
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        //获取变动信息
        List<KiteInstChange> instChangesList = querySceneInstService.listInstChanges(sceneInstId);
        productList.forEach(prodAttrModule ->{
            List<ProdRoleModuleVO> prodRoleModulelist = prodAttrModule.getProdRole();
            prodRoleModulelist.forEach(prodRoleModule -> {
                List<ProdAttrVO> prodAttrVoList = prodRoleModule.getProdAttr().getProdAttrList();
                List<ProdAttrVO> cuccProdAttrList = new ArrayList<>();
                //将属性设置为预览模式，并设置变动标识
                prodAttrVoList.forEach((attr) -> {
                    if(attr.getAttrValues().size()>1&&null!=attr.getValue()&&StringUtils.isNotBlank(attr.getValue())){
                        StaticAttrDO attrValue = attr.getAttrValues().stream().filter(v->v.getAttrValue().equals(attr.getValue())).findFirst().orElse(null);
                        attr.setValueDesc(null==attrValue?"":attrValue.getAttrValueDesc());
                    }
                    CuccProdAttrVO cuccProdAttrVO = new CuccProdAttrVO();
                    KiteBeanUtils.copyProperties(attr, cuccProdAttrVO);
                    for (KiteInstChange kiteInstChange : instChangesList) {
                        if (attr.getFieldName().equals(kiteInstChange.getFieldName())
                            && !KiteStringUtils.isEqual(kiteInstChange.getNewValue(), cuccProdAttrVO.getOldValue())) {
                            cuccProdAttrVO.setNewValue(kiteInstChange.getNewValue());
                            cuccProdAttrVO.setChangeFlag(true);
                            if (KiteStringUtils.equalsAny(cuccProdAttrVO.getFieldName(), "2_0000209","2_0000105")) {
                                String[] regionCodes = KiteStringUtils.split(cuccProdAttrVO.getOldValue(), SymbolConsts.COMMA);
                                List<String> regionNames = Arrays.stream(regionCodes).map(s -> {
                                    UnicomRegion region = unicomRegionService.getRegion(s);
                                    return Objects.nonNull(region) ? region.getRegionName() : "";
                                }).collect(Collectors.toList());
                                cuccProdAttrVO.setOldValueDesc(KiteStringUtils.join(regionNames, SymbolConsts.HYPHEN));
                            }
                            else {
                                String oldValueDesc = Optional.ofNullable(cuccProdAttrVO.getAttrValues().stream().filter(staticAttr -> staticAttr.getAttrValue().equals(cuccProdAttrVO.getOldValue())).findFirst().orElseGet(StaticAttrDO::new).getAttrValueDesc()).orElseGet(String::new);
                                if (KiteStringUtils.isEmpty(oldValueDesc)) {
                                    oldValueDesc = cuccProdAttrVO.getOldValue();
                                }
                                cuccProdAttrVO.setOldValueDesc(oldValueDesc);
                            }

                        }
                    }
                    cuccProdAttrList.add(cuccProdAttrVO);
                });
                prodRoleModule.getProdAttr().setProdAttrList(cuccProdAttrList);
            });
        });
    }

    // 对属性进行分组  -- 由 protected改成public 提供给起租的时候 进行产品属性分组使用
    public void divideProdAttr(List<ProductModuleVO> productModuleVOList, String sceneInstId, String custId,
        Boolean previewFlag) {
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        IQuerySceneFuncProdInstService querySceneFuncProdInstService = SpringUtil
            .getBean(IQuerySceneFuncProdInstService.class);
        //通过dc_public获取分组的配置
        List<DcPublic> dcPublicList = DcPublicCache.get(LocalKeyConsts.GROUP_ATTR);

        for (ProductModuleVO productModuleVO : productModuleVOList) {
            List<ProdRoleModuleVO> prodRoleList = productModuleVO.getProdRole();
            for (ProdRoleModuleVO prodRoleModuleVO : prodRoleList) {

                KiteOfferInst offerInst1 = querySceneInstService.getMainOfferInstByProdInstId(custId, prodRoleModuleVO.getProdInstId());

                productModuleVO.setOfferInstId(Optional.ofNullable(offerInst1).map(KiteOfferInst::getOfferInstId).orElse(""));
                //根据角色获取分组配置
                String roleId = prodRoleModuleVO.getProdRoleId();
                List<DcPublic> roleDcPublicList = dcPublicList.stream().filter(dcPublic -> {
                    return dcPublic.getPkey().equals(roleId);
                }).collect(Collectors.toList());
                //获取产品对应的属性列表
                List<ProdAttrVO> prodAttrList = prodRoleModuleVO.getProdAttr().getProdAttrList();
                if (KiteListUtils.isNotEmpty(roleDcPublicList)) {
                    prodAttrList.forEach(prodAttrVO -> {
                        roleDcPublicList.forEach(dcPublic -> {
                            String codea = dcPublic.getCodea();
                            if (KiteStringUtils.isNotEmpty(codea)) {
                                List<String> codeaList = Arrays.asList(codea.split(SymbolConsts.COMMA));
                                if (codeaList.contains(prodAttrVO.getFieldName())) {
                                    CuccProdAttrVO cuccProdAttrVO = (CuccProdAttrVO) prodAttrVO;
                                    cuccProdAttrVO.setGroupName(dcPublic.getPname());
                                    cuccProdAttrVO.setGroupId(dcPublic.getPcode());
                                }
                            }
                            String codeb = dcPublic.getCodeb();
                            if (KiteStringUtils.isNotEmpty(codeb)) {
                                List<String> codebList = Arrays.asList(codeb.split(SymbolConsts.COMMA));
                                if (codebList.contains(prodAttrVO.getFieldName())) {
                                    prodAttrVO.setShowType(KeyConsts.PROD_ATTR_SHOW_TYPE_D);
                                }
                            }
                        });

                    });
                }
                List<ProdAttrVO> attrList = KiteObjectUtils.clone(prodAttrList);
                Set<String> groupIdSet = new HashSet<>();
                List<GroupProdAttrModuleVO> groupProdAttrs = new ArrayList<>();
                if (KiteListUtils.isNotEmpty(attrList)) {
                    attrList.forEach(prodAttrVO -> {
                        String groupId = prodAttrVO.getGroupId();
                        if (!KiteStringUtils.isEmpty(groupId)) {
                            groupIdSet.add(groupId);
                        }
                    });
                }
                String prodInstId = prodRoleModuleVO.getProdInstId();
                GroupProdAttrModuleVO cardGrp = new GroupProdAttrModuleVO();
                List<CardAttrVO> cardAttrVOS = new ArrayList<>();
                cardGrp.setCardAttrList(cardAttrVOS);
                String offerId = Optional.ofNullable(offerInst1).map(KiteOfferInst::getOfferId).orElse(productModuleVO.getOfferId());
                List<DcPublic> editDc = DcPublicCache.getByPkey("2021110211", offerId);
                groupIdSet.stream().forEach(groupId -> {
                    if (!KiteStringUtils.isEmpty(groupId)) {
                        GroupProdAttrModuleVO groupProdAttr = new GroupProdAttrModuleVO();
                        AttrValue attrValue = AttrValueCache.getAttrValue("2020000002", groupId);
                        /*if (Objects.isNull(attrValue)) {
                            //资费计划，点添加时初始化三个属性组，这里返回三个属性组ID
                            List<AttrValue> attrValues = AttrValueCache.get("2020000002").stream().filter(val -> val.getAttrValue().contains(groupId + ",")).collect(Collectors.toList());
                            if (!KiteListUtils.isEmpty(attrValues)) {
                                attrValue = attrValues.get(0);
                            }
                        }*/
                        // 产品功能类型，前端根据此值判断调功能产品实例化还是接入产品实例化，101是接入产品，其他情况是功能产品
                        String prodFuncType = Optional.ofNullable(attrValue).map(AttrValue::getPartyRoleId).orElse("");
                        groupProdAttr.setProdFuncType(prodFuncType);
                        String showTypeCode = Optional.ofNullable(attrValue).map(AttrValue::getAttrValueCode)
                            .orElse("");
                        String showType = LocalCacheUtils
                            .getAttrValueByAttrIdAndAttrValueCode("2020000003", showTypeCode);
                        List<ProdAttrVO> prodAttrs = new ArrayList<>();
                        List<ButtonAttrVO> buttonAttrList = new ArrayList<>();
                        attrList.forEach(prodAttrVO -> {
                            String attrGroupId = prodAttrVO.getGroupId();
                            String attrValueTypeId = prodAttrVO.getAttrValueTypeId();
                            String attrShowType = prodAttrVO.getShowType();
                            if (KiteStringUtils.isEqual(groupId, attrGroupId) && !KiteStringUtils
                                .isEqual(KeyConsts.PROD_ATTR_SHOW_TYPE_E, attrShowType)) {
                                if (KiteStringUtils.isEqual(KeyConsts.GEN_LOGIC, attrValueTypeId)) {
                                    ButtonAttrVO buttonAttr = new ButtonAttrVO();
                                    buttonAttr.setButtonName(prodAttrVO.getCname());
                                    buttonAttrList.add(buttonAttr);
                                }
                                else {
                                    // 如果是预览页，则需要设置成TT
                                    if (previewFlag) {
                                        if("300000203".equals(prodAttrVO.getFieldName())||KiteStringUtils.equals(prodAttrVO.getPageUrl(),"AttrProdAttachment")){
                                            prodAttrVO.setAttrValueTypeId("98F");
                                        } else {
                                            prodAttrVO.setAttrValueTypeId(LocalKeyConsts.ATTRVALUE_TT);
                                        }
                                    }
                                    prodAttrs.add(prodAttrVO);
                                }
                            }
                        });
                        // 如果prodFuncType为101接入类产品,则获取产品属性
                        dealAccessProdAttrs(groupId, groupProdAttr, prodFuncType, attrList);
                        if (KiteStringUtils.isEqual(LocalKeyConsts.MODULE_TYPE_FORM, showType)) {
                            //不需要更多展示功能，把M全部设置为D
                            String notShowMore = "2000957"; //默认值为物联网分类id

                            String codea = DcPublicCache.getCodea(LocalKeyConsts.SHOW_MORE, "10000");
                            if (StringUtil.isNotEmpty(codea)) {
                                notShowMore = codea;
                            }
                            String cateId = ProductCache.get(productModuleVO.getProdId()).getCateId();
                            if (cateId == null) {
                                cateId = ProductCache.get(productModuleVO.getProdId()).getProdSysNbr();
                            }
                            if (notShowMore.contains(cateId)) {
                                prodAttrs.forEach(attr -> {
                                    if (KeyConsts.PROD_ATTR_SHOW_TYPE_M.equals(attr.getShowType())) {
                                        attr.setShowType(KeyConsts.PROD_ATTR_SHOW_TYPE_D);
                                    }
                                });
                            }
                            groupProdAttr.setFormProdAttrList(prodAttrs);
                        }
                        else if (KiteStringUtils.isEqual(LocalKeyConsts.MODULE_TYPE_TABLE, showType)||(previewFlag&&KiteStringUtils.equalsAny(showType,"cardT","cardF"))) {
                            showType = LocalKeyConsts.MODULE_TYPE_TABLE;
                            // 如果是预览页，则不需要返回
                            if (previewFlag) {
                                groupProdAttr.setButtonAttrList(new ArrayList<>());
                            }
                            else {
                                groupProdAttr.setButtonAttrList(buttonAttrList);
                            }
                            // 补充逻辑,判断如果是101接入产品的时候,根据prodId获取所有接入产品实例。
                            List<KiteProdInstFunc> prodFuncInstList = Lists.newArrayList();
                            if (KiteStringUtils.isEqual(KeyConsts.PROD_FUNC_TYPE_101, prodFuncType)) {
                                List<KiteProdInst> prodInsts = querySceneInstService
                                    .listProdInstsByProdId(sceneInstId, groupId);

                                if (KiteListUtils.isNotEmpty(prodInsts)) {
                                    List<KiteProdInstFunc> finalProdFuncInstList = prodFuncInstList;
                                    prodInsts.stream().forEach(prodInst -> {
                                        List<KiteProdInstFunc> kiteProdInstFuncs = querySceneInstService
                                            .listProdInstFuncs(custId, prodInst.getProdInstId());
                                        kiteProdInstFuncs.stream().forEach(kiteProdInst -> {
                                            kiteProdInst.setAccProdInstId(prodInst.getProdInstId());
                                        });
                                        finalProdFuncInstList.addAll(kiteProdInstFuncs);
                                    });
                                }
                             // 预览的时候需要把删除的功能产品也放进去
                                if (previewFlag) {
                                    dealdelRatePlan(custId, sceneInstId, prodInstId, prodFuncInstList, groupId);
                                }
                            }
                            else {
                                prodFuncInstList = querySceneInstService
                                    .listProdInstFuncsByProdId(custId, prodInstId, groupId);
                             // 预览的时候需要把删除的功能产品也放进去
                                if (previewFlag) {
                                    List<KiteInstChange> instProdFuncChangeList = querySceneInstService.listInstChanges(sceneInstId, InstType.PROD_INST_FUNC);
                                    for (KiteInstChange kiteInstChange : instProdFuncChangeList) {
                                        if (KiteStringUtils.isEqual(kiteInstChange.getNewValue(),ActionType.D.name())
                                            && !KiteStringUtils.isEqual(kiteInstChange.getOldValue(),ActionType.A.name())) {
                                            KiteProdInstFunc delProdFuncInst = querySceneInstService.getProdInstFunc(custId, kiteInstChange.getInstId());
                                            if (Objects.nonNull(delProdFuncInst) && KiteStringUtils.equals(delProdFuncInst.getSpecId(), groupId)) {
                                                prodFuncInstList.add(delProdFuncInst);
                                            }
                                        }
                                    }
                                }
                            }
                            //String ss = JSONObject.toJSON(prodFuncInstList).toString();
                            //System.out.println(ss);

                            if (!KiteListUtils.isEmpty(prodFuncInstList)) {
                                //拼装表头
                                List tableColList = new ArrayList();
                                //拼装表数据
                                List<Map> tableValueList = new ArrayList();
                                List<KiteAttr> commonAttrs = querySceneInstService
                                    .listCommonAttrsByObjId(sceneInstId, groupId);
                                if (!KiteListUtils.isEmpty(commonAttrs)) {
                                    commonAttrs.stream().forEach(attr -> {
                                        Map tableCol = new HashMap();
                                        tableCol.put("dataIndex", attr.getFieldName());
                                        tableCol.put("title", attr.getCname());
                                        tableColList.add(tableCol);
                                    });
                                    if (KiteStringUtils.isEqual(KeyConsts.PROD_FUNC_TYPE_101, prodFuncType)) {
                                        prodFuncInstList.stream().forEach(inst -> {
                                            List<InstAttrDTO> dtoList = querySceneFuncProdInstService
                                                .listProdInstFuncAttrs(sceneInstId, custId, inst.getProdInstId(), null)
                                                .getResultObject();
                                            Map tableValue = new HashMap();
                                            final boolean[] flag = {false};
                                            commonAttrs.stream().forEach(attr -> {
                                                dtoList.stream().forEach(instAttr -> {
                                                    String instShowType = instAttr.getShowType();
                                                    if (StringUtils.equals(attr.getFieldName(), instAttr.getFieldName())
                                                        && !KiteStringUtils
                                                        .isEqual(KeyConsts.PROD_ATTR_SHOW_TYPE_E, instShowType)) {
                                                        if (KiteStringUtils
                                                            .equals(attr.getAttrValueTypeId(), KeyValues.DROPDOWN)
                                                            && KiteStringUtils.isNotEmpty(instAttr.getValueDesc())) {
                                                            if (KiteStringUtils
                                                                .equals("200004020", instAttr.getFieldName())
                                                                || KiteStringUtils
                                                                .equals("200004025", instAttr.getFieldName())
                                                                || KiteStringUtils
                                                                .equals("200004023", instAttr.getFieldName())) {
                                                                Map attrMap = new HashMap();
                                                                attrMap.put("attrValues", instAttr.getAttrValues());
                                                                attrMap.put("value", instAttr.getValue());
                                                                attrMap.put("fieldName", instAttr.getFieldName());
                                                                attrMap.put("accProdInstId", inst.getAccProdInstId());
                                                                attrMap.put("prodInstId", inst.getInstId());
                                                                flag[0] = true;
                                                                tableValue.put(instAttr.getFieldName(), attrMap);
                                                                tableValue.put("defaultField", instAttr.getFieldName());
                                                            }
                                                            else {
                                                                flag[0] = true;
                                                                tableValue.put(instAttr.getFieldName(),
                                                                    instAttr.getValueDesc());
                                                            }
                                                        }
                                                        else if (KiteStringUtils.isNotEmpty(instAttr.getValue())) {
                                                            flag[0] = true;
                                                            tableValue
                                                                .put(instAttr.getFieldName(), instAttr.getValue());
                                                        }
                                                    }
                                                });
                                            });
                                            tableValue
                                                .put("actionType", getActionTypeName(inst.getActionType().name()));
                                            tableValue.put("prodInstId", inst.getAccProdInstId());
                                            if (KiteMapUtils.isNotEmpty(tableValue) && flag[0]) {
                                                tableValueList.add(tableValue);
                                            }
                                        });
                                        /**
                                         * 定制类的资费计划结构是一个接入产品(prod_nbr = 500000000)下挂了三个功能产品,彼此配套
                                         * 当存在多个资费计划实例时,笼统的循环所有的功能产品并设置状态可能会出现A接入产品展示的是
                                         * B接入产品实例下功能产品的状态
                                         * 这里针对这种情况,把所有功能产品按挂的接入产品分组后再对状态做修正
                                         */
                                        Map<String, List<KiteProdInstFunc>> groupFuncInstMap = prodFuncInstList.stream()
                                            .collect(Collectors.groupingBy(KiteProdInstFunc::getAccProdInstId));
                                        if ("500000000".equals(ProductCache.get(groupId).getProdNbr())) {
                                            for (Map tableValue : tableValueList) {
                                                String key = KiteMapUtils.getStrValue(tableValue, "prodInstId");
                                                List<KiteProdInstFunc> sameAccFuncInsts = groupFuncInstMap.get(key);
                                                KiteProdInstFunc actionFunc = sameAccFuncInsts.stream()
                                                    .filter(func -> !ActionType.K.name().equals(func.getActionType().name()))
                                                    .findFirst().orElse(null);
                                                if (Objects.nonNull(actionFunc)) {
                                                    tableValue.put("actionType", getActionTypeName(actionFunc.getActionType().name()));
                                                }
                                            }
                                        }
                                    }
                                    else {
                                        prodFuncInstList.stream().forEach(inst -> {
                                            List<InstAttrDTO> dtoList = querySceneFuncProdInstService
                                                .listAllProdInstFuncAttrs(sceneInstId, custId, inst.getProdInstId())
                                                .getResultObject();
                                            if (KiteStringUtils.equalsAny(ProductCache.get(inst.getSpecId()).getProdNbr(), LocalKeyConsts.FUNC_PROD_ID_APN, LocalKeyConsts.FUNC_PROD_ID_YF5GAPN)) {
                                                Map tableValue = operateSpecialFunc(inst.getProdId(), dtoList);
                                                tableValue.put("prodInstId", inst.getProdInstId());
                                                tableValue
                                                    .put("actionType", getActionTypeName(inst.getActionType().name()));
                                                tableValueList.add(tableValue);
                                            }
                                            else {
                                                Map tableValue = new HashMap();
                                                commonAttrs.stream().forEach(attr -> {
                                                    dtoList.stream().forEach(instAttr -> {
                                                        String instShowType = instAttr.getShowType();
                                                        if (StringUtils
                                                            .equals(attr.getFieldName(), instAttr.getFieldName())
                                                            && !KiteStringUtils
                                                            .isEqual(KeyConsts.PROD_ATTR_SHOW_TYPE_E, instShowType)) {
                                                            if (KiteStringUtils.equalsAny(attr.getAttrValueTypeId(),
                                                                KeyValues.DROPDOWN, KeyValues.IP)) {
                                                                if (KiteStringUtils
                                                                    .equals("200004020", instAttr.getFieldName())
                                                                    || KiteStringUtils
                                                                    .equals("200004025", instAttr.getFieldName())
                                                                    || KiteStringUtils
                                                                    .equals("200004023", instAttr.getFieldName())) {
                                                                    Map attrMap = new HashMap();
                                                                    attrMap.put("attrValues", instAttr.getAttrValues());
                                                                    attrMap.put("value", instAttr.getValue());
                                                                    attrMap.put("fieldName", instAttr.getFieldName());
                                                                    attrMap
                                                                        .put("accProdInstId", inst.getAccProdInstId());
                                                                    attrMap.put("prodInstId", inst.getInstId());
                                                                    tableValue.put(instAttr.getFieldName(), attrMap);
                                                                    tableValue
                                                                        .put("defaultField", instAttr.getFieldName());
                                                                }
                                                                else {
                                                                    tableValue.put(instAttr.getFieldName(),
                                                                        KiteStringUtils
                                                                            .isEmpty(instAttr.getValueDesc()) ?
                                                                            "" :
                                                                            instAttr.getValueDesc());
                                                                }
                                                            }
                                                            else {
                                                                tableValue.put(instAttr.getFieldName(),
                                                                    KiteStringUtils.isEmpty(instAttr.getValue()) ?
                                                                        "" :
                                                                        instAttr.getValue());
                                                            }
                                                        }
                                                    });
                                                });
                                                tableValue.put("prodInstId", inst.getProdInstId());
                                                tableValue
                                                    .put("actionType", getActionTypeName(inst.getActionType().name()));
                                                tableValueList.add(tableValue);
                                            }
                                        });
                                    }
                                    if (!KiteListUtils.isEmpty(tableColList) && !KiteListUtils
                                        .isEmpty(tableValueList)) {
                                        Map tableCol = new HashMap();
                                        tableCol.put("dataIndex", "ctrl");
                                        tableCol.put("title", "操作");
                                        tableColList.add(tableCol);
                                        Map tableMap = new HashMap();
                                        tableMap.put("tableCol", tableColList);
                                        try {
                                            tableValueList.sort(
                                                (o1, o2) -> Integer.parseInt(KiteMapUtils.getString(o2, "prodInstId"))
                                                    - Integer.parseInt(KiteMapUtils.getString(o1, "prodInstId")));
                                        }
                                        catch (Exception e) {
                                            LOGGER.error("排序出错");
                                        }
                                        tableMap.put("tableValue", tableValueList);
                                        groupProdAttr.setTableProdAttr(tableMap);
                                    }
                                }
                            }
                        }else if(KiteStringUtils.equalsAny(showType,"cardT","cardF" )&&!previewFlag){//录入页面卡片类型处理
                            CardAttrVO cardAttrVO = new CardAttrVO();
                            List<KiteProdInstFunc> prodFuncInstList = querySceneInstService
                                .listProdInstFuncsByProdId(custId, prodInstId, groupId);
                            cardAttrVO.setIsSelect("F");
                            cardAttrVO.setCardInstIds("");
                            if(KiteListUtils.isNotEmpty(prodFuncInstList)){
                                cardAttrVO.setIsSelect("T");
                                StringBuffer cardBody = new StringBuffer();
                                //List<KiteAttr> commonAttrs = querySceneInstService.listCommonAttrsByObjId(sceneInstId, groupId);
                                List cardBodyList = new ArrayList();
                               for (KiteProdInstFunc prodFuncInst:prodFuncInstList){
                                    List<KiteAttr> funcAttrs = prodFuncInst.listAttrs();
                                    funcAttrs = funcAttrs.stream()
                                       .sorted(Comparator.comparing(funAttr -> Integer.parseInt(Optional.ofNullable(funAttr.getOrderId()).orElse("0"))))
                                       .collect(Collectors.toList());
                                    String cardBodyStr = "";
                                    for(KiteAttr funcAttr:funcAttrs){
                                        String valueDesc = funcAttr.getValueDesc();
                                        if(!KiteStringUtils.equals(funcAttr.getShowType(),KeyConsts.PROD_ATTR_SHOW_TYPE_D)||KiteStringUtils.isEmpty(valueDesc)){
                                            continue;
                                        }
                                        if(KiteStringUtils.equals(showType,"cardF")){
                                            cardBodyList.add(KiteStringUtils.concatWithSymbol(funcAttr.getCname(),valueDesc,SymbolConsts.PIPELINE));
                                        }else{
                                            if(KiteStringUtils.isEmpty(cardBodyStr)){
                                                cardBodyStr = valueDesc;
                                            }else {
                                                cardBodyStr = KiteStringUtils.concatWithSymbol(cardBodyStr,valueDesc,SymbolConsts.PIPELINE);
                                            }
                                        }
                                    }
                                    if(KiteStringUtils.isNotEmpty(cardBodyStr)){
                                        cardBodyList.add(cardBodyStr);
                                    }
                                }
                                cardAttrVO.setCardBody(cardBodyList);
                                cardAttrVO.setCardInstIds(prodFuncInstList.stream().map(KiteProdInstFunc::getProdInstId).collect(Collectors.joining(",")));
                            }
                            cardAttrVO.setCardId(groupId);
                            cardAttrVO.setCardName(Optional.ofNullable(attrValue).map(AttrValue::getAttrValueName).orElse(""));
                            String orderId = Optional.ofNullable(attrValue).map(AttrValue::getAttrValueSort).orElse("");
                            cardAttrVO.setOrderId(orderId);
                            cardAttrVO.setModuleType(showType);
                            cardAttrVO.setIsEdit("T");
                            String mainServiceOfferId = querySceneInstService.getSceneInst(sceneInstId).getServiceOfferId();
                            String safe_kd_ise = querySceneInstService.getExtParameterValue(sceneInstId, "SAFE_KD_ISE");
                            if(KiteStringUtils.equals(safe_kd_ise,"T")&&KiteStringUtils.equals(offerInst1.getOfferId(),"50000191")){
                                cardAttrVO.setIsEdit("F");
                            }else if(!Objects.equals(offerInst1.getActionType(),ActionType.A)&&KiteListUtils.isNotEmpty(editDc)
                                &&editDc.stream().anyMatch(dc->KiteStringUtils.equalsAny(dc.getPcode(),groupId,SymbolConsts.STAR)&&KiteStringUtils.equals(dc.getCodea(),mainServiceOfferId))){
                                cardAttrVO.setIsEdit("F");
                            }
                            cardAttrVOS.add(cardAttrVO);
                            if(KiteStringUtils.isEmpty(cardGrp.getOrderId())||KiteStringUtils.compare(cardGrp.getGroupId(),orderId)<1){
                                cardGrp.setOrderId(orderId);
                            }
                        }
                        else {
                            groupProdAttr.setFormProdAttrList(prodAttrs);
                        }

                        groupProdAttr.setIsShow("T");
                        groupProdAttr
                            .setOrderId(Optional.ofNullable(attrValue).map(AttrValue::getAttrValueSort).orElse(""));
                        groupProdAttr.setLayoutPage("GroupProdAttrInfo");
                        groupProdAttr
                            .setModuleName(Optional.ofNullable(attrValue).map(AttrValue::getAttrValueName).orElse(""));
                        groupProdAttr.setModuleType(showType);
                        groupProdAttr.setGroupId(groupId);
                        groupProdAttr
                            .setGroupName(Optional.ofNullable(attrValue).map(AttrValue::getAttrValueName).orElse(""));

                     // 如果是预览页，则需要设置成F
                        if (previewFlag) {
                            groupProdAttr.setIsEdit("F");
                            // 预览页面，列表中默认有预览按钮
                            groupProdAttr.setShowPreview("T");
                            // 不可添加
                            groupProdAttr.setShowAdd("F");
                            // 不可编辑
                            groupProdAttr.setShowEdit("F");
                            // 不可删除
                            groupProdAttr.setShowDelete("F");
                        }
                        else if(!KiteStringUtils.equalsAny(showType,"cardT","cardF" )){
                            groupProdAttr.setIsEdit("T");
                            String changeServiceOfferId = querySceneInstService
                                .getExtParameterValue(sceneInstId, "changeServiceOfferId");
                            String serviceOfferId = KiteStringUtils.isNotEmpty(changeServiceOfferId) ? changeServiceOfferId :
                                querySceneInstService.getSceneInst(sceneInstId).getServiceOfferId();

                            if (KiteStringUtils.equalsAny(serviceOfferId, ServiceOfferConsts.SERVICE_OFFER_MODIFY,
                                CuccServiceOfferConsts.SERVICE_OFFER_ADD_PRODUCT_CHANGE)) {
                                //变更业务 新增连接配置按钮展示
                                DcPublic cfg = DcPublicCache.getByPcode("2020121901", productModuleVO.getOfferId(), groupId)
                                    .stream().filter(dcPublic -> dcPublic.getCodea().contains(serviceOfferId))
                                    .findFirst().orElse(null);
                                if (Objects.nonNull(cfg)) {
                                    groupProdAttr.setShowAdd(cfg.getCodeb());
                                    groupProdAttr.setShowPreview(cfg.getCodec());
                                    groupProdAttr.setShowEdit(cfg.getCoded());
                                    groupProdAttr.setShowDelete(cfg.getCodee());
                                    //如果新增、编辑、删除都不允许操作,那么该分组设置不可编辑标识
                                    if (KiteStringUtils.equalsAll(KeyConsts.IFTRUE_F, cfg.getCodeb(), cfg.getCoded(), cfg.getCodee())) {
                                        groupProdAttr.setIsEdit("F");
                                    }
                                }
                                //变更业务 附加产品 新增连接配置按钮展示 状态为新增的附加产品不处理按钮控制
                                DcPublic addDcs = DcPublicCache.getByPcode("2020121902", productModuleVO.getOfferId(), groupId)
                                    .stream().filter(dcPublic -> dcPublic.getCodea().contains(serviceOfferId))
                                    .findFirst().orElse(null);
                                if (Objects.nonNull(addDcs) && !KiteStringUtils.equals(prodRoleModuleVO.getActionType(),ActionType.A.name())) {
                                    groupProdAttr.setShowAdd(addDcs.getCodeb());
                                    groupProdAttr.setShowPreview(addDcs.getCodec());
                                    groupProdAttr.setShowEdit(addDcs.getCoded());
                                    groupProdAttr.setShowDelete(addDcs.getCodee());
                                    //如果新增、编辑、删除都不允许操作,那么该分组设置不可编辑标识
                                    if (KiteStringUtils.equalsAll(KeyConsts.IFTRUE_F, addDcs.getCodeb(), addDcs.getCoded(), addDcs.getCodee())) {
                                        groupProdAttr.setIsEdit("F");
                                    }
                                }
                            }
                            if (KiteStringUtils.equals(serviceOfferId,
                                CuccServiceOfferConsts.SERVICE_OFFER_ADD_TO)) {
                                //变更业务 新增连接配置按钮展示
//                                DcPublic cfg = DcPublicCache.getByPcode("2020121901", specId, groupId).stream()
//                                    .filter(dcPublic -> dcPublic.getCodea().contains(serviceOfferId)).findFirst().orElse(null);
                                // 不可添加
                                groupProdAttr.setShowAdd("F");
                                // 不可编辑
                                groupProdAttr.setShowEdit("F");
                                // 不可删除
                                groupProdAttr.setShowDelete("F");
                                groupProdAttr.setIsEdit("F");
                                // 融合追加产品属性不可修改
                                if (KiteListUtils.isNotEmpty(groupProdAttr.getFormProdAttrList())) {
                                    groupProdAttr.getFormProdAttrList().forEach(prodAttr -> prodAttr.setIsEdit(KeyConsts.IFTRUE_F));
                                }
                            }
                            // 趸交支付详情场景，分组设置不可编辑标识
                            String payDetailFlag = querySceneInstService.getExtParameterValue(sceneInstId, "PAY_DETAIL_FLAG");
                            if (KiteStringUtils.isNotEmpty(payDetailFlag) && KeyConsts.IFTRUE_T.equals(payDetailFlag)) {
                                groupProdAttr.setIsEdit("F");
                                //前端是否大带宽取属性本身isEdit 趸交支付场景置灰
                                if(KiteStringUtils.equals(groupProdAttr.getGroupId(),"300000204")){
                                    groupProdAttr.getFormProdAttrList().forEach(attr->{
                                        if(KiteStringUtils.equals(attr.getFieldName(),"2_0000078")){
                                            attr.setIsEdit("F");
                                        }
                                    });
                                }
                            }
                            // 物联网受理单补录不允许修改信息
                            String taskCode = querySceneInstService.getExtParameterValue(sceneInstId, "taskCode");
                            if (KiteStringUtils.equals(taskCode, "OrderAddRecordWLWXS")) {
                                groupProdAttr.setShowAdd("F");
                                groupProdAttr.setShowEdit("F");
                                groupProdAttr.setShowDelete("F");
                                groupProdAttr.setIsEdit("F");
                            }
                        }
                        if (Objects.nonNull(attrValue)) {
                            if(previewFlag||!KiteStringUtils.equalsAny(showType,"cardT","cardF" )){
                                groupProdAttrs.add(groupProdAttr);
                            }
                        }
                    }
                });
                if(KiteListUtils.isNotEmpty(cardAttrVOS)){
                    List<CardAttrVO> cardAttrVOSRes = cardAttrVOS.stream()
                        .sorted(Comparator.comparing(groupProdAttr -> Integer.parseInt(groupProdAttr.getOrderId())))
                        .collect(Collectors.toList());
                    cardGrp.setCardAttrList(cardAttrVOSRes);
                    cardGrp.setIsEdit("T");
                    cardGrp.setIsShow("T");
                    cardGrp.setGroupName("办理包");
                    cardGrp.setModuleName("办理包");
                    cardGrp.setModuleType("CARD");
                    groupProdAttrs.add(cardGrp);
                }
                List<GroupProdAttrModuleVO> resGroupProdAttrs = groupProdAttrs.stream()
                    .sorted(Comparator.comparing(groupProdAttr -> Integer.parseInt(groupProdAttr.getOrderId())))
                    .collect(Collectors.toList());
                prodRoleModuleVO.setGroupProdAttr(resGroupProdAttrs);
            }
        }
    }

    /**
     * 处理接入类产品属性
     *
     * @param groupId
     * @param groupProdAttr
     * @param prodFuncType
     */
    private static void dealAccessProdAttrs(String groupId, GroupProdAttrModuleVO groupProdAttr, String prodFuncType,
        List<ProdAttrVO> attrList) {
        if (KiteStringUtils.isEqual(KeyConsts.PROD_FUNC_TYPE_101, prodFuncType) || LocalKeyConsts.FUNC_PROD_ID_5GQP
            .equals(groupId) || "300000204".equals(groupId)) {
            List<ProdAttrVO> prodAttrVOList = new ArrayList<>();
            if (KiteListUtils.isNotEmpty(attrList)) {
                attrList.stream().forEach(attr -> {
                    if (KiteStringUtils.isEqual(attr.getGroupId(), groupId) && !KiteStringUtils.isEqual(attr.getAttrValueTypeId(), "98H")) {
                        prodAttrVOList.add(attr);
                    }
                });
            }
            groupProdAttr.setFormProdAttrList(prodAttrVOList);
        }
    }

    private static Map operateSpecialFunc(String funcProdId, List<InstAttrDTO> dtoList) {
        Map tableValue = new HashMap();
        if (KiteStringUtils.isEqual("300000150", funcProdId) || KiteStringUtils.isEqual("30000015011", funcProdId)
            || KiteStringUtils.isEqual("30000015012", funcProdId) || KiteStringUtils.isEqual("300001000", funcProdId)) {
            String apnName = Optional.ofNullable(dtoList.stream().filter(dtoAttr -> KiteStringUtils.equals(dtoAttr.getFieldName(), "200002833")).findFirst().orElse(null)).map(InstAttrDTO::getValue).orElse("待生成");
            dtoList.stream().forEach(instAttr -> {
                String fieldName = instAttr.getFieldName();
                String value = instAttr.getValue();
                if (KiteStringUtils.isEqual("200003996", fieldName)) {
                    if (KiteStringUtils.isEqual("100006950", value)) {
                        //共享vpn
                        dtoList.stream().forEach(dto -> {
                            if (KiteStringUtils.isEqual("200003997", dto.getFieldName())) {
                                tableValue.put("200004135", dto.getValueDesc());
                                tableValue.put("200002833", dto.getValueDesc());
                            }
                            if (KiteStringUtils.isEqual("200003996", dto.getFieldName())) {
                                tableValue.put("apnType", dto.getValueDesc());
                            }
                            if (KiteStringUtils.isEqual("200004084", dto.getFieldName())) {
                                tableValue.put(dto.getFieldName(), dto.getValueDesc());
                            }
                        });
                    }
                    else if (KiteStringUtils.isEqual("100006951", value)) {
                        //使用已创建的vpn
                        dtoList.stream().forEach(dto -> {
                            if (KiteStringUtils.isEqual("200003998", dto.getFieldName())) {
                                tableValue.put("200004135", dto.getValueDesc());
                                tableValue.put("200002833", dto.getValueDesc());
                            }
                            if (KiteStringUtils.isEqual("200003996", dto.getFieldName())) {
                                tableValue.put("apnType", dto.getValueDesc());
                            }
                        });
                    }
                    else if (KiteStringUtils.isEqual("100006952", value)) {
                        //我要定制
                        dtoList.stream().forEach(dto -> {
                            if (KiteStringUtils.isEqual("200004135", dto.getFieldName())) {
                                tableValue.put("200004135", dto.getValueDesc());
                                tableValue.put("200002833", apnName);
                            }
                            if (KiteStringUtils.isEqual("200003999", dto.getFieldName())) {
                                tableValue.put("apnType", dto.getValueDesc());
                            }
                            if (KiteStringUtils.isEqual("200004084", dto.getFieldName())) {
                                tableValue.put(dto.getFieldName(), dto.getValueDesc());
                            }
                        });
                    }
                }
            });
        }
        return tableValue;
    }

    private static String getActionTypeName(String actionType) {
        String actionTypeName;
        switch (actionType) {
            case "A":
                actionTypeName = "新增";
                break;
            case "M":
                actionTypeName = "修改";
                break;
            case "D":
                actionTypeName = "删除";
                break;
            case "K":
                actionTypeName = "原有";
                break;
            case "X":
                actionTypeName = "成员退出5G切片";
                break;
            default:
                actionTypeName = "删除(A->D)";
                break;
        }
        return actionTypeName;
    }

    private static void dealdelRatePlan(String custId, String sceneInstId, String prodInstId, List<KiteProdInstFunc> kiteProdInstFuncs, String groupId) {
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        List<KiteInstChange> instProdFuncChangeList = querySceneInstService.listInstChanges(sceneInstId, InstType.PROD_INST_FUNC);
        List<KiteProdInstFunc> delFunInstList = Lists.newArrayList();
        KiteProdInstFunc delBaseFunInst = null;
        for (KiteInstChange kiteInstChange : instProdFuncChangeList) {
            if (KiteStringUtils.isEqual(kiteInstChange.getNewValue(),ActionType.D.name())
                && !KiteStringUtils.isEqual(kiteInstChange.getNewValue(),ActionType.A.name())) {
                KiteProdInstFunc delProdFuncInst = querySceneInstService.getProdInstFunc(custId, kiteInstChange.getInstId());
                if (Objects.nonNull(delProdFuncInst)) {
                    if (KiteStringUtils.isNotEmpty(delProdFuncInst.getAccProdInstId())) {
                        KiteProdInst delProdInst = querySceneInstService.getProdInst(custId, delProdFuncInst.getAccProdInstId());
                        if (Objects.nonNull(delProdInst) && KiteStringUtils.equals(delProdInst.getSpecId(), groupId)
                            && KiteStringUtils.equalsAny(delProdInst.getActionType().name(), ActionType.D.name(), ActionType.X.name())) {
                            delBaseFunInst = delProdFuncInst;
                            kiteProdInstFuncs.add(delProdFuncInst);
                        }
                    }
                    else {
                        delFunInstList.add(delProdFuncInst);
                    }
                }
            }
        }
        if (Objects.nonNull(delBaseFunInst) && KiteListUtils.isNotEmpty(delFunInstList)) {
            // 资费服务 资费计划标识
           KiteAttr rateServiceAttr = delBaseFunInst.getAttrMap().get("200004145");
           if (Objects.isNull(rateServiceAttr)) {
               rateServiceAttr = delBaseFunInst.getAttrMap().get("200004129");
           }
           if (Objects.isNull(rateServiceAttr)) {
               rateServiceAttr = delBaseFunInst.getAttrMap().get("200004146");
           }
           for (KiteProdInstFunc delFunInst : delFunInstList) {
               KiteAttr rateBaseAttr = delFunInst.getAttrMap().get("200004129");
               KiteAttr rateDiscAttr = delFunInst.getAttrMap().get("200004146");
               KiteAttr rateServAttr = delFunInst.getAttrMap().get("200004145");
               if ((Objects.nonNull(rateBaseAttr) && KiteStringUtils.equals(rateServiceAttr.getValue(), rateBaseAttr.getValue()))
                   || (Objects.nonNull(rateDiscAttr) && KiteStringUtils.equals(rateServiceAttr.getValue(), rateDiscAttr.getValue()))
                   || (Objects.nonNull(rateServAttr) && KiteStringUtils.equals(rateServiceAttr.getValue(), rateServAttr.getValue()))) {
                   delFunInst.setAccProdInstId(delBaseFunInst.getAccProdInstId());
                   kiteProdInstFuncs.add(delFunInst);
               }

           }
        }
    }
}
